重新思考响应式网页设计

2025-06-10

重新思考响应式网页设计

从想法到革命性的网络网格系统;)


我们现在做得怎么样了?

说实话,我们大多数人从来没有做过响应式网页设计,我们都只是制作自适应网页(我们只关心几个特定的​​屏幕尺寸)并称之为响应式!

来自:[https://4eps1j19gvc31lua5g49gnl7-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/responsive-design.png](https://4eps1j19gvc31lua5g49gnl7-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/responsive-design.png)

响应式的意思更接近上述内容。但我们能实现它吗?

多年来,我一直在大学里做用户体验讲座,向学生们展示这张图片,告诉他们这是一个真正的响应式设计,但我意识到,我们做不到。实际上,没有一个网格框架(就我所知)能够完成这项任务。

由于响应式网页设计没有终极解决方案,我们大多数人坚持使用类似 Bootstrap 网格系统之类的系统。不幸的是,这类网格系统远非响应式设计,而且与当前的 FE 技术栈配合得也不好。

从现在开始,我会经常提到 Bootstrap 网格系统。这样一来,我指的是一组网格系统(Bootstrap、Foundation、Tailwind CSS 等),而不是单指 Bootstrap。

类似 Bootstrap 的网格有什么问题?

最好先从一个例子开始。为了说明还有更多类似于 Bootstrap 的网格系统,我们来看一下 Tailwind 的网格:

    <div class="flex flex-wrap">
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 mb-4 bg-gray-500"></div>
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 mb-4 bg-gray-400"></div>
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 mb-4 bg-gray-500"></div>
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 mb-4 bg-gray-400"></div>
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/2 xl:w-1/6 mb-4 bg-gray-500"></div>
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/2 xl:w-1/6 mb-4 bg-gray-400"></div>
    </div>
Enter fullscreen mode Exit fullscreen mode

开发人员对于上述代码有什么抱怨?

  • 这是很多代码。
  • 它很难读。
  • 这很难推理。

开发人员想要的是摆脱这种情况,w-full sm:w-1/2 md:w-1/3 lg:w-1/4 xl:w-1/6 mb-4 bg-gray-400转而采用如下方式:col-2

用户体验设计师对于网格有什么抱怨呢?

  1. 它不支持大屏幕。
  2. 它与组件配合得不太好。
  3. 它允许您声明针对特定条件的行为,而不是让您声明针对该行为的规则。

让我们更详细地研究一下上述三点。

1)宽屏支持

只需在 4k 或 8k 显示器上尝试随机 Web 即可;)

类似 Bootstrap 的网格是自适应的。这意味着它们有一些屏幕尺寸限制;它们使用断点。最大的尺寸——xl,通常代表 1200px 左右。任何大于 1200px 的尺寸都无关紧要,你需要自行处理其响应速度。很多网页在大屏幕上会卡住或看起来非常奇怪。

2)网格与组件

类似 Bootstrap 的网格在组件内部几乎毫无用处。为什么?

假设你有一个宽度为 400px 的组件,其中包含四个宽度为 200px 的子元素。显然,它的内容需要与同一组件的另一个宽度为 800px 的实例表现不同,对吧?在第一种情况下,你更喜欢 2x2 的网格,在另一种情况下,你更喜欢 4x1 的网格。不幸的是,由于两个实例的组件代码相同,并且屏幕尺寸是给定的,你……

Bootstrap 示例中的列宽由百分比定​​义

替代文本

由于我们已经处于组件时代(React、Angular、Vue、Svelte、Web Components)……类似引导程序的网格似乎注定要失败,但没有什么东西可以取代它们,至少没有可以在所有前端框架中使用的通用的东西。

您仍然可以使用类似 Bootstrap 的网格系统以及面向组件的框架进行页面/应用布局。但说实话,当您看到这种网格系统会生成多少 CSS 代码,以及实际布局中会用到多少类时,最好还是放弃它。您随时可以实现自定义解决方案。

解决方案,修复上面的 Bootstrap 示例表单,似乎是具有最小和最大宽度的列的定义。

列采用所需的宽度并按比例消耗剩余部分。

替代文本

3)网格的行为

引导网格“让你声明特定条件下的行为,而不是让你声明该行为的规则”,这种说法听起来有点哲学。翻译成人类的语言:

Bootstrap 网格允许您在特定断点处声明某些块的大小(您需要用自己的过度声明式代码覆盖所有页面宽度的情况,例如 Tailwind 示例)。通常,必须编写大量代码才能实现一个简单的目标:使元素在任何屏幕尺寸下都保持相同的大小。Bootstrap 网格系统的附加价值仅仅是将内容与网格对齐。
我们真正想要的是声明一组规则,并让网格的内容基于这些规则进行流动、跨越、收缩和拉伸。

我们能否跳过所有屏幕尺寸的声明,并自动对齐到网格?是的,我们可以!

我知道,当你切换到智能“自动”网格时,与你的设计师/产品负责人争论起来可能会很困难。你只需要向他们解释,即使他们为你提供了移动端、平板和桌面端的设计,也总会有一些介于两者之间的设计,而这些设计是他们无法控制的。设计应该基于指南、组件库以及对布局规则的基本理解,而不是仅仅基于几个像素级完美的模拟;)

新网格——设计头脑风暴

真正响应的网格系统应该具备哪些特征?

  1. 与屏幕尺寸无关可在组件中使用)。
  2. 网格应包含与虚拟网格对齐的元素(网格间隙应在所有方向上精确对齐)
  3. 网格容器的子容器可以跨越多个虚拟列(最好也可以跨越行)
  4. 列应具有最佳大小,并以诸如或 之类的单位pxrem给出,而不是百分比。仅以百分比定义列的问题在于,它迫使我们针对特定断点(例如 sm、md、lg)定义元素的行为。百分比在不同条件下代表不同的实际大小。
  5. 网格应该由列定义,而不是像 Bootstrap 那样反过来。Bootstrap 网格始终有 12 列;对于移动设备来说太多,而对于超高清屏幕来说又太少。
  6. 列应该适应容器大小(如果列比容器宽,它应该缩小到容器的宽度)。

新电网——选择技术

使用什么技术?可用的技术似乎是 Flex-box 和 CSS Grid。它们似乎都能满足我们的大部分需求,但并非全部。让我们看看这些方法的不足之处:

弹性盒

如果我们想避免以父元素的百分比定义列,我们需要通过类似以下的方式定义网格元素:

.col {min-width:100px; max-width:200px;}
Enter fullscreen mode Exit fullscreen mode

遗憾的是,这仅在最后一个 .col 元素与网格容器右边缘对齐时才有效。如果第一行有 3 个 .col 元素,而第二行只有 2 个 .col 元素,则这些元素将不再与虚拟网格对齐。此行为无法修复。这对于 Flex-box 来说是行不通的。

网格

display: grid表现更好一些,我们可以使用:

    grid-template-columns: repeat(auto-fit, minmax($grid-col-width, 1fr));
Enter fullscreen mode Exit fullscreen mode

auto-fit告诉网格拉伸现有列,直到有空间容纳新列。
minmax()定义列的最小宽度和最大宽度。最小值表示所需的列宽,最大值(1fr) 表示列的宽度为 1/列数,如果列数不足,则以最小宽度填充容器。

它的作用与上面的弹性框示例完全相同,不同之处在于它始终适合网格布局,太棒了!但它还有另一个缺陷。当你告诉一个元素跨越三列,但只有两列适合容器时,跨越的元素就会溢出容器。这个问题唯一有意义的解决方案似乎是期待已久的元素查询(“响应式条件适用于页面元素,而不是浏览器的宽度或高度”的查询)。由于它们仍处于开放提案的形式,我不得不自己编写“元素查询”程序。

元素查询

我最初尝试使用某种 polyfill,但那些支持良好的 polyfill 速度慢且相对较大(大约一千行代码)。由于我的目标是构建一个超小型的网格框架,所以不得不另辟蹊径。最合适的方案是使用新的“ResizeObserver”和“customElements”JS API。它们的支持程度并非最佳(约占全球市场的 70%),但速度很快,并且完全符合需求。我的网格元素查询大约只需要 35 行代码,这太棒了。

所需的 CSS 和 JS 代码大小为 1KB(gzip 压缩后),并涵盖了头脑风暴部分的所有要求。实际上,它的功能远不止于此!

我现在跳过实施细节并向您展示结果,我的网格可以做什么;)

“Eq 网格”

为了避免分别提供 JS 和 CSS、为 DOM 元素添加事件监听器、监听 DOM 变化等等,我创建了一个“自定义元素”,您只需导入并初始化即可。它会根据提供的参数生成所有必需的 CSS 类。您只需要:

npm i eq-grid --save
Enter fullscreen mode Exit fullscreen mode

然后在你的 main.js 文件中:

import { initEqGrid } from 'eq-grid';
initEqGrid(120, 10, 'px', 10); // ['column width', 'gap width', 'units', 'max-columns-span/collapse']
Enter fullscreen mode Exit fullscreen mode

从那时起,您可以<eq-grid>在 html 模板中使用元素,并且所有神奇的操作都在后台完成。

它几乎可以在任何地方运行,包括纯 JS/HTML、React、Angular、Vue、Svelte 和其他现代框架。

让我们看一些例子...只需以全屏模式打开以下沙箱并尝试调整它们的大小。

用于内容的网格:

适用于文章预告、卡片、缩略图等


在上面的例子中,您可以看到类.eq-col-3-5 .eq-col-2-4,您可以使用它们以声明方式覆盖网格的自动行为。

嵌套网格:


通过嵌套,您可以避免某些元素自由地跨“行”排列。这在创建如下所示的布局时非常有用。

用于布局的网格:


.eq-col-1你可能会想,为什么右侧的 网格这么宽?这怎么可能?这里的根网格只有两.eq-col-1列,左侧的所有内容都位于一个嵌套网格中。每列的最小宽度为 100px,最大宽度为 1fr(父级宽度的一部分)。在这种情况下,最大值占主导地位。如果根网格中有很多元素,则改用 min(100px) 规则。这适用于左侧的嵌套网格。

请记住,子网格的内容不会对其父网格产生影响。

顺便说一下,这个示例有 3 个嵌套网格。使用这种嵌套技术,您可以更好地控制折叠或拉伸的内容、时间以及如何折叠或拉伸。
这对于大型布局非常有用。

Eq Grid 和 rem

rem当您将网格设置为使用单位时,它还可以提供另一个很酷的功能:

initEqGrid(10, 1, 'rem');
Enter fullscreen mode Exit fullscreen mode

任何使用rem单位的元素都会根据其字体大小计算其大小HTML。这使我们能够通过HTML元素上的媒体查询来缩放列。如果我们使用多边形流体尺寸调整技术,则可以线性缩放字体。下面我将字体稍微缩放到 1280px。然后,我开始以与窗口增长相同的速度缩放。

html {
  font-size: 14px;
}

@media screen and (min-width: 320px) {
  html {
    font-size: calc(14px + 4 * ((100vw - 320px) / 960));
  }
}

@media screen and (min-width: 1280px) {
  html {
    font-size: calc(18px + 158 * ((100vw - 1280px) / 10000));
  }
}

@media screen and (min-width: 11280px) {
  html {
    font-size: 176px;
  }
}
Enter fullscreen mode Exit fullscreen mode

上述操作与 eq-grid 结合使用的效果rems非常棒。一旦窗口宽度超过 1280px,所有内容(网格、字体等)都会像放大一样开始缩放。这样,您就可以在 8k 显示器上清晰地查看网页。您可以设置缩放和添加新列之间的比例——只需调整字体大小18px + 158176px即可。

请参阅此处的示例(您需要点击“打开沙盒按钮”,否则它将无法工作)。然后缩小视图查看其工作原理 ;)

结论

我希望 Eq Grid 系统能够满足所有常见的开发/用户体验需求。您可以以非常简单和自动化的方式使用它,让内容像第一张图片中的水一样流动。或者,您可以更具声明性,根据网格大小微调网格元素的折叠和收缩方式。这取决于您的需求。

  • 它确实反应灵敏。

  • 它可以从零扩展到无限,而不会影响用户体验。

  • 这也是我自己的想法的第一次实现,它肯定可以改进,所以......

如果您能留下评论,我将不胜感激——您的想法、您错过的内容,或者您​​喜欢/不喜欢的地方。任何反馈都将不胜感激!也许我们可以让网格系统在组件时代再次变得可行。

您可以在 npm 上查看 eq-grid 网格:eq-grid on npm
这里描述了所有 Eq-grid 类——它们的作用以及如何使用它们。
您还可以查看如何在 React 应用中使用网格。

鏂囩珷鏉ユ簮锛�https://dev.to/rezi/rethinking-responsive-webdesign-1a7g
PREV
VS Code:搜索并替换正则表达式
NEXT
React 组件 props 的 TypeScript 类型或接口