网页自适应设计

4,301 阅读31分钟

入坑前端2年了,今天摸鱼无聊温习了下自适应,发现我还是太菜了~~~~~~ 给大家分享下,不喜勿喷哦, 搬砖不易~~~~

媒体查询

媒体查询使用 @media 关键字(CSS @ 规则)启动,可用于各种用例。

针对不同类型的输出

网站通常显示在屏幕上,但 CSS 也可用于为其他输出设置网站样式。 您可能希望网页在屏幕上以一种方式显示,但输出时则有所不同。 通过查询媒体类型,这成为可能。

body {
  color: black;
  background-color: grey;
}
​
@media print {
  body {
    background-color: transparent;
  }
}

使用 @media @ 规则,也可以创建单独的样式表并对 link 元素使用 media 属性:

<link rel="stylesheet" href="global.css">
<link rel="stylesheet" href="print.css" media="print">

如果您没有为 CSS 指定任何媒体类型,则 CSS 会自动将其媒体类型值设为 all

查询条件

@media type and (feature)
<link rel="stylesheet" href="specific.css" media="type and (feature)">

假设您想要根据浏览器窗口是处于横向模式(视口宽度大于其高度)还是纵向模式(视口高度大于宽度)应用不同的样式。您可以使用一项名为 orientation 的媒体功能进行测试:

媒体类型为 all。这是默认值,如果需要,您可以将其省略。

<link rel="stylesheet" href="landscape.css" media="all and (orientation: landscape)">
<link rel="stylesheet" href="portrait.css" media="all and (orientation: portrait)">
等效
<link rel="stylesheet" href="landscape.css" media="(orientation: landscape)">
<link rel="stylesheet" href="portrait.css" media="(orientation: portrait)">
@media all and (orientation: landscape) {
   // Styles for landscape mode.
}
@media all and (orientation: portrait) {
   // Styles for portrait mode.
}
等效
@media (orientation: landscape) {
   // Styles for landscape mode.
}
@media (orientation: portrait) {
   // Styles for portrait mode.
}

虽然对不同的媒体类型(如 print)使用不同的样式表可能没有问题,但建议您为每个媒体查询使用单独的样式表。请改用 @media @ 规则。

根据视口大小调整样式

如需在浏览器窗口宽度超过特定宽度时应用样式,请使用 min-width

@media (min-width: 400px) {
  // Styles for viewports wider than 400 pixels.
}

使用 max-width 媒体功能应用特定宽度以下的样式:

@media (max-width: 400px) {
  // Styles for viewports narrower than 400 pixels.
}

如果您的内容主要基于图片,那么使用像素可能最为合适。 如果您的内容主要是文本,那么使用基于文本大小的相对单位(例如 emch)可能更加合理:

@media (min-width: 25em) {
  // Styles for viewports wider than 25em.
}

还可以组合媒体查询以应用多个条件。 使用 and 来合并您的媒体查询:

@media (min-width: 50em) and (max-width: 60em) {
  // Styles for viewports wider than 50em and narrower than 60em.
}

根据内容选择断点

最好根据内容(而不是热门设备尺寸)选择断点,因为断点会因每个技术发布周期而发生变化。

50em 是文本行过长的点。 因此,我们创建了一个断点,使界面更易于阅读。 使用 column-count 属性,文本从该点开始分为两列。

@media (min-width: 50em) {
  article {
    column-count: 2;
  }
}

组合

您可以根据视口的高度(而不仅仅是宽度)使用媒体查询。 这对于优化“首屏”的界面内容非常有用。在前面的示例中,如果读者使用较宽但较短的浏览器窗口,必须向下滚动一列,然后向上滚动,直到第二列的顶部。只有当视口足够宽且足够高时,才应用列,这样会更加安全。

您可以合并媒体查询,以便样式仅在所有条件均为 true 时应用。 在本例中,视口的宽度必须至少为 50em,高度至少为 60em,才能应用列样式。 这些断点是根据内容量选择的。

@media (min-width: 50em) and (min-height: 60em) {
  article {
    column-count: 2;
  }
}

宏布局

宏布局描述了界面的较大、页面组织结构。

两列布局的线框,位于与窄视图的一列相同的布局旁边。

在应用任何布局之前,您应确保内容的流畅性是合理的。 这种单列的默认排序方式是较小屏幕的呈现顺序。

<body>
  <header>…</header>
  <main>
    <article>…</article>
    <aside>…</aside>
  </main>
  <footer>…</footer>
</body>

排列这些单独的网页级组件时,您实际上是在设计一个宏布局:网页的高级视图。使用媒体查询,您可以在 CSS 中提供规则,用于描述应如何根据不同的屏幕尺寸调整此视图。点击查看

网格

CSS 网格是将布局应用到网页的绝佳工具。 在上面的示例中,假设您在有足够的可用屏幕宽度后使用两列布局。 如需在浏览器足够宽后应用此两列布局,请使用媒体查询定义指定断点上方的网格样式。

@media (min-width: 45em) {
  main {
    display: grid;
    grid-template-columns: 2fr 1fr;
  }
}

Flexbox

@media (min-width: 45em) {
  main {
    display: flex;
    flex-direction: row;
  }

  main article {
    flex: 2;
  }

  main aside {
    flex: 1;
  }
}

微型布局

在布局方面,我们通常会考虑到页面级别的设计。 不过,页面内的较小组件也可以有自己的独立布局。

理想情况下,无论这些组件级布局在页面上的位置如何,它们都会自动自动调整。您可能不知道某个组件会被放置到主要内容列和/或边栏中。 不知道组件最终会在何处,您需要确保组件能够自行调整以适应其容器。

一种两列布局,一宽一窄。根据媒体对象是宽列还是窄列,媒体对象的布局会有所不同。

注意 :将来,通过实现容器查询,创建能够适应容器的组件将变得更加简单。不过,目前,您需要考虑创建可重复使用的自适应微布局的现有方式。在此单元结束时,您可以预览容器查询如何适应现有的自适应设计方法。

网格

CSS 网格不仅仅适用于页面级布局。 它还非常适合其中的组件。

在此示例中,::before::after 伪元素会在标题的任意一侧创建装饰线。标题本身是一个网格容器。 各个元素的布局方式应确保线条始终填满可用空间。

h1 {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1em;
}
h1::before,
h1::after {
  content: "";
  border-top: 0.1em double black;
  align-self: center;
}

Firefox 中的开发者工具显示网格叠加层。

Chrome 中的开发者工具,显示了网格叠加层。

Flexbox

flexbox 可让组件更加灵活。您可以声明组件中的哪些元素应具有最小或最大尺寸,并让其他元素相应地灵活适应。

在此示例中,图片占用了四分之一的可用空间,文字占用了四分之三的可用空间。 但图片的尺寸绝不会超过 200 像素。

.media {
  display: flex;
  align-items: center;
  gap: 1em;
}
.media-illustration {
  flex: 1;
  max-inline-size: 200px;
}
.media-content {
  flex: 3;
}

Firefox 中的开发者工具,显示 Flexbox 叠加层。

容器查询

Flexbox 让您可以从内容开始进行设计。 您可以指定元素的参数(元素应多窄、应有多宽),然后让浏览器确定最终的实现方法。

但是,组件本身并不知道其上下文。它不知道该标识是正用在主要内容中还是边栏中。 这可能会使组件布局比页面布局更复杂。 为了能够应用与上下文相关的样式,您的组件需要不仅仅知道它们所在的视口的大小,

使用网页布局时,您确实可以知道容器的宽度,因为容器是浏览器视口;媒体查询会报告网页级容器的尺寸。

注意 :容器查询是一项新的实验性技术,并未广泛应用于浏览器。若要测试以下代码并查看可正常运行的示例,请在 Chrome 中启用容器查询。转到 chrome://flags/,搜索 Container Queries,然后启用 #enable-container-queries 标志。启用此标记后,您可以在 Chrome 开发者工具中检查和调试容器查询

首先,请定义哪些元素将用作容器。

main,
aside {
  container-type: inline-size;
}

这意味着您希望能够查询内嵌维度。 对于英语文档,相当于横轴。 您将根据容器的宽度更改样式。

如果某个组件位于上述某个容器内 您可以通过与媒体查询非常相似的方式应用样式

.media-illustration {
  max-width: 200px;
  margin: auto;
}

@container (min-width: 25em) {
  .media {
    display: flex;
    align-items: center;
    gap: 1em;
  }

  .media-illustration {
    flex: 1;
  }

  .media-content {
    flex: 3;
  }
}

如果媒体对象位于小于 25em 的容器内,则不会应用 Flexbox 样式。图片和文字将垂直排列。

但是,如果所包含元素的宽度大于 25em,图片和文字会并排显示。

借助容器查询,您可以独立设置组件的样式。 视口的宽度不再是重要的因素。 您可以根据所包含元素的宽度编写规则。

两个不同大小的容器。

合并查询

您可以对页面布局使用媒体查询,对页面内的组件使用容器查询。

在这里,页面的整体结构包含一个 main 元素和一个 aside 元素。这两个元素中都有媒体对象。

<body>
  <main>
     <div class="media"></div>
     <div class="media"></div>
  </main>
  <aside>
     <div class="media"></div>
  </aside>
</body>

当视口宽度大于 45em 时,媒体查询会向 mainaside 元素应用网格布局。

@media (min-width: 45em) {
  body {
    display: grid;
    grid-template-columns: 3fr 1fr;
  }
}

媒体对象的容器查询规则保持不变:仅当所包含元素的宽度大于 25em 时,才应用水平 Flexbox 布局。

一种双列布局,一宽一窄。 根据媒体对象是宽列还是窄列,媒体对象的布局会有所不同。

排版

如果您没有为文本指定任何样式,浏览器会应用其自己的默认样式。这些称为用户代理样式表,可能会因浏览器而异。用户也可以设置自己的文本显示偏好设置。

如果您未指定行长,浏览器将在屏幕边缘自动换行文本。因此,网页上的文字在默认情况下是响应式的,其文字排版可以适应用户的视口。

文字与屏幕相称并不意味着文字阅读起来舒适。良好的排版是以适当的方式呈现文本的关键。排版不仅仅是选择合适的字体,您需要考虑用户的偏好设置、文本大小、行长和文本行之间的距离

文字大小

如果用户使用的是小屏幕,那么可以放心,他们的屏幕会非常靠近他们的眼睛。

但随着屏幕越来越大,建立这种联系变得更加困难。笔记本电脑大小的屏幕可能非常靠近观看者,而宽屏桌面显示器与电视屏幕差不多。用户距离桌面设备屏幕只有一臂远,但距离电视却有很大的距离。

尽管您无法确定用户与屏幕之间的距离,但可以尝试使用最终显示适合的文本大小。对于较小的屏幕,请使用较小的文字;较大的屏幕可以使用较大的文字。

当屏幕尺寸变宽时,您可以使用媒体查询更改 font-size 属性。

@media (min-width: 30em) {
  html {
    font-size: 125%;
  }
}

@media (min-width: 40em) {
  html {
    font-size: 150%;
  }
}

@media (min-width: 50em) {
  html {
    font-size: 175%;
  }
}

@media (min-width: 60em) {
  html {
    font-size: 200%;
  }
}

缩放文本

在特定断点处的固定文字大小之间切换非常复杂。响应性更强的方法是让用户设备的宽度影响文字大小。

CSS 中的 vw 单位表示“视口宽度”。将字体大小与视口的宽度相关联意味着文本将根据浏览器宽度成比例缩放。这使得很难预测任意特定宽度下的文字大小,但您知道文字大小将适合用户的浏览器宽度。

切勿在字体大小声明中单独使用 vw

错误做法

html {
  font-size: 2.5vw;
}

否则,用户将无法调整文本大小。如果您混用 emremch 等相对单位,则文本可调整大小。CSS calc() 函数是实现此目的的理想之选。

正确做法

html {
  font-size: calc(0.75rem + 1.5vw);
}

让浏览器来记录。这样便很难准确预测在任何特定宽度下文字大小的具体大小,但您知道文字大小会处于正确的范围。用户的浏览器负责准确计算文字大小。

但现在,有可能文字在窄屏幕上过小,在宽屏设备上却过大。

限制文本

您可能不想让文本缩小并放大到极端。您可以使用 CSS clamp() 函数来控制扩缩的开始和结束位置。这会将缩放“限制”到特定范围。

clamp() 函数与 calc() 函数类似,但它接受三个值。中间值与您传递给 calc() 的值相同。起始值指定了最小字号,在本例中为 1rem,以确保不低于用户的首选字体大小。结束值用于指定最大大小。

html {
  font-size: clamp(1rem, 0.75rem + 1.5vw, 2rem);
}

现在,文本大小会根据用户的屏幕按比例缩小和增大,但文本大小绝不会低于 1rem 或超过 2rem

行长

不能直接在 CSS 中设置行长。但可以通过限制容器的宽度来防止文本过宽。max-inline-size 属性非常适合这种情况。

错误做法

article {
  max-inline-size: 700px;
}

正确做法

article {
  max-inline-size: 66ch;
}

如果宽度使用 ch 单位,则新行会在该字体大小的第 66 个字符处换行。

行高

对于较短的文本行,line-height 值可以较大。但是,如果您为长行文本使用较大的 line-height 值,则读者很难从一行的结尾转到下一行的开头。

article {
  max-inline-size: 66ch;
  line-height: 1.65;
}
blockquote {
  max-inline-size: 45ch;
  line-height: 2;
}

line-height 声明中使用无单位值。这可确保行高相对于 font-size

错误做法

line-height: 24px;

正确做法

line-height: 1.5;

网页字体

使用 @font-face 告知浏览器在哪里可以找到您的网页字体文件。使用 woff2 作为网页字体格式。这种广告系列得到了很好的支持,效果提升最为理想。

@font-face {
  font-family: Roboto;
  src: url('/fonts/roboto-regular.woff2') format('woff2');
}
body {
  font-family: Roboto, sans-serif;
}

但是,您添加的每个网页字体文件都可能会因为增加网页加载时间而降低用户体验。请注意,设计不仅仅是最终像素的外观。这些像素的绘制速度是用户体验的关键部分。快速的用户体验是一种良好的用户体验。

字体加载

您可以请求浏览器尽快开始下载字体文件。在引用网页字体文件的文档的 head 中添加一个 link 元素。值为 preloadrel 属性会告知浏览器优先加载该文件。值为 fontas 属性可告知浏览器这是什么类型的文件。您可以使用 type 属性进行更具体的设置。

<link href="/fonts/roboto-regular.woff2" type="font/woff2" 
  rel="preload" as="font" crossorigin>

即使您自行托管字体文件,也需要添加 crossorigin属性。

使用 CSS font-display 属性告知浏览器如何管理从系统字体到网页字体的切换。您可以选择在网页字体加载完成之前不显示任何文字。您可以选择立即显示系统字体,然后在网页字体加载后立即切换到该字体。这两种策略都有缺点。如果您等到网页字体下载完成后再显示任何文字,用户可能会发现自己长时间盯着空白页,导致他们感到沮丧。如果您先以系统字体显示文字,然后又切换为网页字体,则网页上的内容可能会出现突兀的情况。

注意 :您可以在 @font-face 规则中使用 size-adjust,减轻文本偏移的不适影响。

@font-face {
  font-family: "Adjusted Typeface";
  size-adjust: 150%;
  src: url(some/path/to/typeface.woff2) format('woff2');
}

0. 创建一个名为 Adjusted Typeface 的自定义字体。

  1. 使用 size-adjust 将每个字形放大到其默认大小的 150%。
  2. 仅影响这个导入的单个字体。

使用上面的自定义字体,如下所示:

h1 {
  font-family: "Adjusted Typeface";
}

如果您仍希望网页字体在每次网页字体最终加载时都替换系统字体,请使用 swapfont-display 值。

body {
  font-family: Roboto, sans-serif;
  font-display: swap;
}

如果您希望在文本渲染后继续使用系统字体,请使用 fallbackfont-display 值。

body {
  font-family: Roboto, sans-serif;
  font-display: fallback;
}

自适应图片

限制图片

在样式表中,您可以使用 max-inline-size 声明图片的渲染尺寸绝不应超过其包含元素的尺寸。

浏览器支持

  • 谷歌57
  • Edge79
  • 火狐41
  • Sari12.1

来源

img {
  max-inline-size: 100%;
  block-size: auto;
}

注意 :如果您愿意,可以使用 max-width 而不是 max-inline-size,但请注意,最好养成从逻辑属性角度思考的习惯。

您也可以将同一规则应用于其他类型的嵌入内容,如视频和 iframe。

img,
video,
iframe {
  max-inline-size: 100%;
  block-size: auto;
}

应用该规则后,浏览器会自动缩小图片以使其适合屏幕大小。

两个屏幕截图;第一张显示超出浏览器宽度的展开图片;第二张显示被限制在浏览器视口内的同一图片。转存失败,建议直接上传图片文件

添加 autoblock-size 值意味着图片的宽高比将保持不变。

有时,图片的尺寸可能会超出您的控制范围,例如通过内容管理系统添加图片时。如果您的设计要求图片的宽高比与图片实际尺寸不同,请在 CSS 中使用 aspect-ratio 属性。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
}

但是,浏览器可能会挤压或拉伸图片,以使其符合您的首选宽高比。

为避免出现这种情况,请使用 object-fit 属性。

object-fit 值为 contain 会告知浏览器保留图片的宽高比,即使这意味着要在上方和下方留出空白区域。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: contain;
}

一只看起来很漂亮的狗狗的侧面像,嘴里叼着一个球;图片两侧有额外的空间。

object-fit 值为 cover 会告知浏览器保留图片的宽高比,即使这意味着将图片的顶部和底部剪裁也是如此。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: cover;
}

一只看起来很漂亮的狗狗的侧面像,嘴里叼着一个球;图片的顶部和底部经过了剪裁。

如果顶部和底部均匀剪裁造成问题,请使用 object-position CSS 属性调整剪裁的焦点。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: cover;
  object-position: top center;
}

传送图片

大小调整提示

如果您知道图片的尺寸,则应添加 widthheight 属性。即使图片以不同的尺寸呈现(借助 max-inline-size: 100% 规则),浏览器仍然知道宽高比,并且可以留出适量空间。这样即可阻止图片加载时其他内容跳动。

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
>

正在加载提示

您可以使用 loading 属性指示浏览器是否延迟加载图片,直到图片进入或靠近视口为止。对于非首屏图片,请使用值 lazy。除非用户向下滚动足够长的距离,使图片显示出来,否则浏览器不会加载延迟图片。如果用户从不滚动,则图片永远不会加载。点击查看

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
>

对于首屏的主打图片,不应使用 loading。如果您的网站自动应用 loading="lazy" 属性,您通常可以设置 eager 属性(这是默认值),以防止应用此属性:

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
>

提取优先级

对于 LCP 图片等重要图片,您可以使用提取优先级进一步确定加载优先级,只需将 fetchpriority 属性设置为 high 即可:

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
 fetchpriority="high"
>

这将告知浏览器立即以高优先级提取图片,而不是等到浏览器在正常提取时完成布局。

但请注意:当您要求浏览器优先下载一种资源(例如图片)时,浏览器必须降低下载脚本或字体文件等其他资源的优先级。仅当图片确实很重要时,才对其设置 fetchpriority="high"

预加载提示

某些图片可能不会显示在初始 HTML 中,前提是它们是通过 JavaScript 添加的,或者作为 CSS 中的背景图片添加。您还可以使用预加载功能提前提取这些重要图片。对于非常重要的图片,可以将此属性与 fetchpriority 属性结合使用:

<link rel="preload" href="hero.jpg" as="image" fetchpriority="high">

同样,请谨慎使用此方法,避免过度替换浏览器优先级启发式算法,从而可能导致性能下降。

尽可能避免预加载,并且在初始 HTML 中提供图片,避免重复代码,并允许访问浏览器支持的所有选项。

图像解码

您还可以向 img 元素中添加 decoding 属性。您可以告知浏览器图片可异步解码。然后,浏览器可以优先处理其他内容。

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
>

如果图片本身是最重要的内容,可以使用 sync 值来优先处理。

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
 decoding="sync"
>

decoding 属性不会更改图片解码的速度,而只会更改浏览器是否会在渲染其他内容之前等待此类图片解码完成。

在大多数情况下,这几乎不会产生任何影响,但在某些情况下,图片或内容的显示速度可能会略快一些。例如,对于包含大量元素需要花费时间渲染的大型文档,以及需要花费一定时间解码的大型图片,针对重要图片设置 sync 会告知浏览器等待该图片并同时渲染这两张图片。或者,设置 async 可以更快地显示内容,而无需等待图像解码。

不过,较好的选择通常是尝试避免 DOM 大小过多,并确保使用响应式图片以缩短解码时间,这意味着解码属性几乎没有任何影响。

srcset 的自适应图片

得益于 max-inline-size: 100% 声明,您的图片绝不会脱离容器。但是,即使大图片缩小以适合大小看起来没问题,也会感觉不舒服。如果用户在低带宽网络中使用小屏幕设备,则会下载不必要的大图片。

如果您以不同尺寸制作了同一张图片的多个版本,则可以使用 srcset 属性告知浏览器这些版本。

宽度描述符

您可以传入以英文逗号分隔的值列表。每个值都应该是图片的网址,后跟一个空格,然后是图片的一些元数据。这些元数据称为描述符。

在此示例中,元数据使用 w 单位描述每张图片的宽度。一个 w 对应 1 个像素。

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 300w,
  medium-image.png 600w,
  large-image.png 1200w"
>

srcset 属性不会取代 src 属性。不过,srcset 属性是对 src 属性的补充。您仍然需要有效的 src 属性,但现在浏览器可以将该属性的值替换为 srcset 属性中列出的某个选项。

除非需要,否则浏览器不会下载较大的图片。这样可以节省带宽。

尺寸

如果您使用了宽度描述符,则还必须使用 sizes 属性向浏览器提供更多信息。该属性可告知浏览器您希望图片在不同条件下显示的大小。这些条件在媒体查询中指定。

sizes 属性接受以英文逗号分隔的媒体查询和图片宽度列表。

注意 :在 HTML 元素中使用 CSS 媒体查询会让人感到很奇怪。它破坏了呈现方式和结构的分离。但这是及时提供必要尺寸信息以取得有效效果的唯一方式。

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 300w,
  medium-image.png 600w,
  large-image.png 1200w"
 sizes="(min-width: 66em) 33vw,
  (min-width: 44em) 50vw,
  100vw"
>

在本例中,您要告知浏览器:在视口宽度为 66em 以上时,显示的图片宽度不超过屏幕宽度的三分之一(例如,在三列布局内)。

对于视口宽度介于 44em66em 之间的图片,以屏幕宽度的一半显示图片(两列布局)。

对于 44em 以下的任何值,均以屏幕全宽显示图片。

这意味着,最大的图片不一定会在最宽的屏幕上使用。可以显示多列布局的宽浏览器窗口将使用能容纳在一列中的图片。该图片可能比在较窄的屏幕上用于单列布局的图片小。

像素密度描述符

在另一种情况下,您可能需要提供同一张图片的多个版本。

某些设备具有高密度显示屏。在双密度显示屏上,您可以将两像素的信息量打包到一个像素的空间中。这可让图片在此类显示屏上清晰可见。

同一张图片的两个版本,是一只看起来很开心的狗狗,嘴里叼着一个球体,一张图片看起来很清爽,另一张则看起来模糊不清。

密度描述符用于在 src 属性中描述图片与图片相关的像素密度。密度描述符是一个数字后跟字母 x:1x2x 等。

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 1x,
  medium-image.png 2x,
  large-image.png 3x"
>

如果 small-image.png 的大小为 300 x 200 像素,而 medium-image.png 的大小为 600 x 400 像素,那么 medium-image.pngsrcset 列表中可以有 2x

您不必使用整数。如果图片的其他版本尺寸为 450x300 像素,您可以使用 1.5x 来描述它。

注意 :您可以使用宽度描述符或密度描述符,但不能同时使用这两者。

演示性图片

HTML 中的图片即内容。因此,您始终需要为屏幕阅读器和搜索引擎提供 alt 属性,其中包含图片说明。

如果您嵌入的只是纯粹的视觉效果,没有任何有意义的内容,请使用空的 alt 属性。

<img
 src="flourish.png"
 alt=""
 width="400"
 height="50"
>

您仍必须添加 alt 属性。缺少的 alt 属性与空的 alt 属性不同。空的 alt 属性会向屏幕阅读器传达此图片是演示图片。

理想情况下,演示性或装饰性图片不应位于 HTML 中。HTML 是用于结构的。CSS 用于演示。

背景图片

使用 CSS 中的 background-image 属性来加载展示性图片。

element {
  background-image: url(flourish.png);
}

您可以使用 background-imageimage-set 函数指定多个候选图片。

CSS 中的 image-set 函数的运作方式与 HTML 中的 srcset 属性非常相似。提供图像列表,其中包含每个图像的像素密度描述符。

element {
  background-image: image-set(
    small-image.png 1x,
    medium-image.png 2x,
    large-image.png 3x
  );
}

浏览器会根据设备的像素密度选择最合适的图片。

在向网站添加图片时,您需要考虑多种因素:

为每张图片预留适当的空间。 弄清楚您需要多少尺寸。 确定图片是内容图片还是装饰图片。

花时间修正图片是值得的。糟糕的图片策略会导致用户感到沮丧和厌烦。无论用户使用何种设备或网络连接,良好的图片策略都能让您的网站看起来简洁明快。

您的工具包中还有另一个 HTML 元素(picture 元素),以帮助您对图片进行更多控制。

图片元素

srcsetsrc 属性为基础,picture 元素也以 img 元素为基础。picture 元素封装了 img 元素。

<picture>
  <img src="image.jpg" alt="A description of the image.">
</picture>

如果 picture 元素中嵌套没有 img 元素,则 picture 元素将不起作用。

srcset 属性一样,picture 元素会更新该 img 元素中 src 属性的值。不同之处在于,srcset 属性为浏览器提供建议,而 picture 元素则会提供命令。这样,您便拥有控制权。

source

您可以在 picture 元素中指定多个 source 元素,每个元素都有自己的 srcset 属性。然后,浏览器会尽可能执行第一个任务。

图片格式

<picture> 
	<source srcset="image.avif" type="image/avif"> 
	<source srcset="image.webp" type="image/webp"> 
	<img src="image.jpg" alt="A description of the image."   width="300" height="200" loading="lazy" decoding="async">
</picture>

第一个 source 元素指向采用新 AVIF 格式的图片。如果浏览器能够呈现 AVIF 图片,那么这就是它选择的图片文件。否则,它会移至下一个 source 元素。

第二个 source 元素指向一张 WebP 格式的图片。如果浏览器能够呈现 WebP 图片,则会使用该图片文件。

否则,浏览器将回退到 img 元素的 src 属性中的图片文件。该图片为 JPEG 格式。

这意味着,您可以在不牺牲向后兼容性的情况下开始使用新的图片格式。

在此示例中,type 属性会告知浏览器指定了哪种类型的图片格式。

图片尺寸

除了切换图片格式之外,您还可以切换图片大小。media 属性用于告知浏览器图片的显示宽度。在 media 属性中添加媒体查询。

<picture>
  <source srcset="large.png" media="(min-width: 75em)">
  <source srcset="medium.png" media="(min-width: 40em)">
  <img src="small.png" alt="A description of the image." 
    width="300" height="200" loading="lazy" decoding="async">
</picture>

上述代码将告知浏览器,如果视口宽度大于 75em,则必须使用大图片。在 40em75em 之间,浏览器必须使用中等图片。浏览器必须使用 40em 以下小图片。

这与在 img 元素中使用 srcsetsizes 属性不同。在这种情况下,您需要向浏览器提供建议。source 元素更像是一个命令,而不是建议。

您还可以在 source 元素的 srcset 属性内使用像素密度描述符。

<picture>
  <source srcset="large.png 1x" media="(min-width: 75em)">
  <source srcset="medium.png 1x, large.png 2x" media="(min-width: 40em)">
  <img src="small.png" alt="A description of the image." width="300" height="200" loading="lazy" decoding="async"
    srcset="small.png 1x, medium.png 2x, large.png 3x">
</picture>

在该示例中,您仍在告知浏览器在不同断点处执行什么操作,但现在浏览器可以选择根据设备的像素密度选择最合适的图片。

剪裁

如果您只需投放同一图片的不同尺寸版本,srcset 是您的最佳选择。但是,如果图片在较小尺寸下看起来不美观,您可以尝试改用剪裁后的图片。

不同的图片可能具有不同的宽度和高度,以便更好地适应上下文。例如,在移动浏览器中,您可能需要呈现较宽和较窄的剪裁,而在桌面浏览器中,可能需要显示较宽和较短的剪裁。

下面的主打图片示例会根据视口宽度改变其内容和形状。为每个 source 元素添加 widthheight 属性。

<picture>
  <source srcset="full.jpg" media="(min-width: 75em)" width="1200" height="500">
  <source srcset="regular.jpg" media="(min-width: 50em)" width="800" height="400">
  <img src="cropped.jpg" alt="A description of the image." width="400" height="400" loading="eager" decoding="sync">
</picture>

请注意,您无法根据图片来源更改 alt 属性。您需要编写一个 alt 属性,用于描述完整尺寸的图片和剪裁后的图片。

对于大多数自适应图片,您可能不需要使用 picture 元素,因为 img 元素上的 srcsetsizes 属性可以满足很多用例的需求。但对于需要更精细的控制的情形,picture 元素是一款强大的工具。

界面模式

导航

在大屏幕上,显示导航链接列表非常简单。其中有充足的空间容纳这些链接。

在小屏幕上,空间非常宝贵。当您针对这种情况进行设计时,很容易想将导航隐藏在按钮后面。这种解决方案的问题在于,用户必须执行两个步骤才能到达任意位置:打开菜单,然后选择一个选项。在菜单打开之前,用户一直想知道“在哪里可以去?”

尝试找到一种避免隐藏导航的策略。如果商品数量相对较少,则可以设置导航栏样式,使其在小屏幕上的显示效果良好。

同一个网站,包含 5 个导航链接,分别在移动浏览器和平板电脑浏览器中查看。导航界面会在两台设备上显示。

如果导航中包含大量链接,该模式无法缩放。在小屏幕上,如果链接成两行或三行,导航会显得杂乱无章。

一种可能的解决方案是将链接保持在一行上,但将列表截断在屏幕边缘。用户可以水平滑动以显示不立即显示的链接。这是溢出模式。

此方法的优势在于,它可以适应任何设备宽度和任意数量的链接。其缺点是用户可能会错过最初不可见的链接。如果您对主导航采用这种方法,请确保前几个链接是最重要的,并直观地表明列表中有更多项。上面的示例为此指示器使用了渐变效果。

万不得已时,您可以选择默认隐藏导航,并提供一种供用户显示和隐藏内容的切换机制。这称为渐进式披露。

同一个网站,包含 5 个导航链接,分别在移动浏览器和平板电脑浏览器中查看。导航在平板电脑上可见,但在移动设备上隐藏。

轮播广告

适用于导航的原则也适用于其他内容:无论如何都不要隐藏任何内容。轮播是隐藏内容的常见方法。它看起来可能非常简洁,但用户很有可能永远不会发现隐藏的内容。轮播界面能够更好地解决组织问题(例如应该在首页上显示哪些内容),而不是为用户提供服务。

也就是说,如果空间有限,轮播界面可以防止网页过长而杂乱无章。您可以采用混合方法:针对小屏幕以轮播方式显示内容,而针对大屏幕以网格形式显示相同的内容。

对于较窄的屏幕,使用 Flexbox 成行显示项目。内容行会超出屏幕边缘。使用 overflow-x: auto 可允许水平滑动。

@media (max-width: 50em) {
  .cards {
    display: flex;
    flex-direction: row;
    overflow-x: auto;
    scroll-snap-type: inline mandatory;
    scroll-behavior: smooth;
  }
  .cards .card {
    flex-shrink: 0;
    flex-basis: 15em;
    scroll-snap-align: start;
  }
}

注意overflow-x 的逻辑版本为 overflow-inline,它与 scroll-snap-type 的值更匹配。此示例使用实体版本以获得更好的跨浏览器支持。

scroll-snap 属性可确保项能顺畅地滑动。在 scroll-snap-type: inline mandatory 的帮助下,这些项会扣合到位。

当屏幕足够大(在本例中为比 50em 宽)时,可切换到网格,以行和列显示项,而不隐藏任何内容。

@media (min-width: 50em) {
  .cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
  }
}

轮播界面是实际运用的溢出模式的另一个示例。如果有许多用户可以浏览的商品,即使在大屏幕(包括电视)上,也可以继续使用溢出模式。此媒体滚动条使用多个轮播界面来管理大量选项。

同样,scroll-snap 属性可确保互动顺畅。另请注意,轮播界面中的图片已应用了 loading="lazy"。在这种情况下,图片并非在非首屏位置,而是在边缘以外,但同样的原则是一样的:如果用户从未滑动到相关项的距离,则图片不会被下载,从而节省带宽。

​​

注意 :前面的示例显示了一个更完整的演示,如需了解详情,请参阅构建媒体滚动条组件一文。

数据表格

table 元素非常适合用于设计表格数据的结构,即包含相关信息的行和列。但是,如果表格过大,则可能会破坏小屏幕的布局。

您可以将溢出模式应用于表。在此示例中,表封装在具有 table-container 类的 div 中。

.table-container {
  max-inline-size: 100%;
  overflow-x: auto;
  scroll-snap-type: inline mandatory;
  scroll-behavior: smooth;
}
.table-container th, 
.table-container td {
  scroll-snap-align: start;
  padding: var(--metric-box-spacing);
}

​​

最后官方还列举了折叠屏手机的相关配置,不过我暂时用不上就没学习了 传送门

以上内容来自 web.dev/ 我只是简单的搬运工