首页 > 解决方案 > 仅使用 CSS 重构响应式设计中的部分

问题描述

您将如何在移动版和桌面版布局中完全重构网页的各个部分?我想实现类似于以下的布局:

Desktop:
--------
Primary         |   Complementary 1
                |   Complementary 2
Secondary       |

Mobile:
-------
Complementary 1
Primary
Complementary 2
Secondary

注意:Desktop 中的分隔线应该是一条直线,Complementaries 具有固定宽度,最大宽度,Primary/Secondary 填充页面的其余部分。此外,所有部分的高度都不同。还要注意移动设备中的交错顺序。所有这一切都阻止了我使用简单的 flexbox 方法,使用 order 和 row/column 来实现这一点。

他们的看法是:桌面中清晰的水平分离只有通过将两列都放在一个 div 中才是真正可行的——但这本质上会阻止移动布局。如果有一种方法可以通过 css 完全忽略包装 div,那么它可能是可能的,但我从来没有想过。

任何想法都值得赞赏 - 使用 Javascript 这当然是可能的,但如果有一个聪明的、或多或少纯 CSS 的解决方案,我会非常喜欢它。

标签: htmlcssmedia-queriesresponsive

解决方案


正如上面评论中提到的,这可以使用 CSS 声明相对容易地实现,display: grid并将其设置为所需大小的媒体查询。

如果您首先以您希望将内容显示为单列的方式构建内容(即Complementary 1,,Primary...),那么您可以简单地使用 a min-width(无论您希望最小宽度是什么)创建一个媒体查询,然后使用网格以相应地列出内容。例如:

/* Set grid layout for screens larger than 700px only */
@media (min-width: 700px) {
  .grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-column-gap: 2em;
  }
  
  /* place sections into relevant columns/rows */
  .grid main {
    grid-column-start: 1;
    grid-row-start: 1;
  }
  
  .grid section {
    grid-column-start: 1;
    grid-row-start: 3;
  }
  
  .grid aside {
    grid-column-start: 2;
    grid-row-start: 1;
  }
  
  .grid main + aside {
    grid-column-start: 2;
    grid-row-start: 2;
  }
  
  /* Add a rule between the aside and the main content */
  aside {
    padding-left: 2em;
    border-left: 1px solid #aaa;
  }
}
<section class="grid">
  <aside>
    <p>Complementary 1</p>
  </aside>
  
  <main>
    <h1>Main content</h1>
    <p>Your main content can go here...</p>
  </main>
  
  <aside>
    <p>Complementary 2</p>
  </aside>
  
  <section>
    <h1>Secondary content</h1>
    <p>Your secondary content can go here...</p>
  </section>
</section>

需要注意的一件事是,在上面的示例中,您的“辅助内容”似乎开始于“补充”内容的下方。我不确定这是否只是格式错误 - 如果这不是故意的,您可以grid-row-start酌情调整。

编辑:

您可以使用 使列与大小无关display: contain,但请注意 - 对此的支持非常糟糕!如果可访问性不是一个特别关注的问题,这应该就足够了。

如果可访问性一个问题,您可以使用 JavaScript 相对轻松地实现以下目标,只需将mainandsection元素包装在一个 div 中,然后asides根据屏幕大小将 div 包装在另一个 div 中。这将解决糟糕的支持问题,这只会使display: contain元素有问题invisible(因此<div>使用 JavaScript 删除包装将有效地做与将其设置为相同的事情display: contain)。

希望这能给你一个前进的方向。

.grid {
  display: flex;
  flex-wrap: wrap;
}

.grid > div {
  display: contents;
}

.grid aside {
  order: 1;
}

.grid aside + aside {
  order: 3;
}

.grid main {
  order: 2;
}

.grid section {
  order: 4;
}

.grid main,
.grid section,
.grid aside {
  width: 100%;
}

/* Set grid layout for screens larger than 700px only */
@media (min-width: 700px) {
  .grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-column-gap: 2em;
  }
  
  .grid > div {
    display: block;
  }
  
  /* Add a rule between the aside and the main content */
  .grid > div + div {
    padding-left: 2em;
    border-left: 1px solid #aaa;
  }
  
  /* Set order back to 0 */
  .grid section,
  .grid main,
  .grid aside {
    order: unset;
  }
}
<section class="grid">
  <div>
    <main>
      <h1>Main content</h1>
      <p>Your main content can go here...</p>
    </main>

    <section>
      <h1>Secondary content</h1>
      <p>Your secondary content can go here...</p>
    </section>
  </div>
  
  <div>
    <aside>
      <p>Complementary 1</p>
      <p>Complementary 1</p>
      <p>Complementary 1</p>
      <p>Complementary 1</p>
      <p>Complementary 1</p>
      <p>Complementary 1</p>
    </aside>

    <aside>
      <p>Complementary 2</p>
    </aside>
  </div>
</section>


推荐阅读