CSS `Typographic Systems`:`rem`, `em`, `vw`, `vh` 字体单位的高级应用

各位前端小伙伴们,早上好!我是你们的老朋友,今天咱们不聊八卦,就来好好聊聊CSS里的那些“量体裁衣”的字体单位:rememvwvh。 别觉得它们是老生常谈,真正用好了,能让你的页面在各种设备上都展现出最佳的阅读体验。咱们争取把这些单位的特性、应用场景和一些高级技巧都给它扒个精光!

第一部分:rem – 根的守护者

rem (root em) 这玩意儿,顾名思义,就是相对于根元素(通常是<html>)的字体大小来计算的。 这就像有个统一的标尺,所有元素的字体大小都基于它来调整。

  • 基础用法:

    html {
      font-size: 16px; /* 设定根元素的字体大小 */
    }
    
    body {
      font-size: 1rem; /* 相当于 16px */
    }
    
    h1 {
      font-size: 2rem; /* 相当于 32px */
    }
    
    p {
      font-size: 0.875rem; /* 相当于 14px (16 * 0.875) */
    }

    简单吧? rem 就像一个锚点,所有的字体大小都以它为基准。

  • 优势:

    • 易于维护: 修改根元素的 font-size,就能全局调整所有使用 rem 单位的字体大小。这对响应式设计尤其有用。
    • 避免嵌套问题: 不像 em 单位会受到父元素字体大小的影响,rem 始终相对于根元素,避免了复杂的嵌套计算。
  • 进阶用法:响应式排版

    rem 最强大的地方在于它可以结合 Media Queries 实现响应式排版。 我们可以根据屏幕大小来调整根元素的 font-size,从而实现全局的字体缩放。

    html {
      font-size: 16px; /* 默认字体大小 */
    }
    
    @media (max-width: 768px) {
      html {
        font-size: 14px; /* 小屏幕时缩小字体 */
      }
    }
    
    @media (max-width: 480px) {
      html {
        font-size: 12px; /* 更小的屏幕时进一步缩小字体 */
      }
    }
    
    body {
      font-size: 1rem; /* 相当于 16px, 14px, 或 12px, 取决于屏幕大小 */
    }

    这样,当屏幕变小时,页面上的所有字体都会相应缩小,而不需要单独修改每个元素的 font-size。是不是很方便?

  • 更高级的用法:配合 calc() 函数

    有时候,我们可能需要更精细的控制。比如,希望字体大小随着屏幕尺寸的变化而平滑变化。 这时候,calc() 函数就派上用场了。

    html {
      font-size: calc(12px + (16 - 12) * ((100vw - 320px) / (1200 - 320)));
      /*
        解释一下:
        - 12px 是最小字体大小
        - 16px 是最大字体大小
        - 320px 是最小屏幕宽度
        - 1200px 是最大屏幕宽度
        - 这个公式会根据屏幕宽度在 12px 和 16px 之间平滑调整字体大小
      */
    }
    
    body {
      font-size: 1rem;
    }

    这个公式可能有点复杂,但它的核心思想是:根据屏幕宽度,线性地调整根元素的字体大小。 这能让字体大小在不同屏幕尺寸之间过渡得更加自然。

  • rem 的最佳实践:

    • 设定合理的根字体大小: 常见的做法是设置为 16px,方便计算。

    • 使用预处理器: 如果你使用 Sass 或 Less,可以定义一个函数或 Mixin,将 px 转换为 rem,避免手动计算。

      // Sass 示例
      @function pxToRem($pxValue) {
        $remValue: $pxValue / 16px * 1rem;
        @return $remValue;
      }
      
      body {
        font-size: pxToRem(14px); // 输出 font-size: 0.875rem;
      }
    • 考虑用户偏好: 有些用户可能会在浏览器中自定义字体大小。 为了尊重用户的偏好,可以考虑使用 em 单位作为 rem 的补充。

第二部分:em – 上下文的舞者

em 单位是相对于当前元素的字体大小来计算的。 这意味着,em 的大小会受到父元素字体大小的影响。

  • 基础用法:

    body {
      font-size: 16px;
    }
    
    h1 {
      font-size: 2em; /* 相当于 32px (16 * 2) */
    }
    
    p {
      font-size: 0.875em; /* 相当于 14px (16 * 0.875) */
    }
    
    .box {
      font-size: 1.2em; /* 相当于 19.2px (16 * 1.2) */
      padding: 1em; /* 相当于 19.2px (19.2 * 1) */
    }

    注意,.boxpadding 也是基于 .box 自身的 font-size 来计算的。

  • 优势:

    • 局部调整: em 单位可以方便地调整某个区域的字体大小,而不会影响全局的排版。
    • 继承性: em 单位会继承父元素的字体大小,这使得它非常适合用于创建具有层次结构的布局。
  • 劣势:

    • 嵌套问题: 如果多个元素嵌套在一起,并且都使用了 em 单位,那么字体大小的计算会变得非常复杂。
    • 维护困难: 当父元素的字体大小发生变化时,所有子元素的字体大小都会受到影响,这可能会导致意想不到的布局问题。
  • 高级用法:组件化设计

    em 在组件化设计中非常有用。 我们可以将组件的字体大小设置为 em,这样就可以通过修改组件的父元素的字体大小来整体调整组件的大小。

    <div class="card">
      <h2>Card Title</h2>
      <p>This is the card content.</p>
      <button>Read More</button>
    </div>
    .card {
      font-size: 1em; /* 默认字体大小 */
      border: 1px solid #ccc;
      padding: 1em;
    }
    
    .card h2 {
      font-size: 1.5em;
    }
    
    .card p {
      font-size: 0.875em;
    }
    
    .card button {
      font-size: 0.75em;
    }
    
    /* 通过修改父元素的字体大小来整体调整组件的大小 */
    .card.large {
      font-size: 1.2em;
    }
    
    .card.small {
      font-size: 0.8em;
    }

    通过给 .card 元素添加不同的 class,我们可以轻松地调整整个卡片的大小,而不需要单独修改每个元素的样式。

  • em 的最佳实践:

    • 谨慎使用: 尽量避免在深层嵌套的元素中使用 em 单位,以防止字体大小计算过于复杂。
    • 配合 rem 使用: 可以使用 rem 单位设置全局的字体大小,然后使用 em 单位在局部进行调整。
    • 善用 CSS Variables: 使用 CSS Variables 可以更方便地控制 em 单位的大小。

第三部分:vwvh – 视口的探险家

vw (viewport width) 和 vh (viewport height) 分别代表视口宽度和视口高度的百分比。 它们可以用来创建基于视口大小的布局。

  • 基础用法:

    h1 {
      font-size: 5vw; /* 字体大小为视口宽度的 5% */
    }
    
    p {
      font-size: 2vh; /* 字体大小为视口高度的 2% */
    }
    
    .box {
      width: 50vw; /* 宽度为视口宽度的 50% */
      height: 30vh; /* 高度为视口高度的 30% */
    }
  • 优势:

    • 简单直观: vwvh 单位可以很方便地创建与视口大小相关的布局。
    • 全屏布局: 它们非常适合用于创建全屏布局,例如全屏轮播图或全屏导航。
  • 劣势:

    • 字体大小变化过大: 在不同的屏幕尺寸下,vwvh 单位可能会导致字体大小变化过大,影响阅读体验。
    • 缺乏上下文: vwvh 单位不考虑元素的上下文,可能会导致布局出现问题。
  • 高级用法:响应式视频背景

    我们可以使用 vwvh 单位来创建一个响应式的视频背景,使其始终占据整个视口。

    <div class="video-background">
      <video autoplay loop muted>
        <source src="your-video.mp4" type="video/mp4">
      </video>
    </div>
    .video-background {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      overflow: hidden;
      z-index: -1; /* 将视频背景置于底层 */
    }
    
    .video-background video {
      /*
        确保视频始终覆盖整个容器
        object-fit: cover; 会保持视频的宽高比,并裁剪视频以适应容器
      */
      min-width: 100%;
      min-height: 100%;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      object-fit: cover;
    }

    这段代码会将视频置于页面的最底层,并使其始终占据整个视口,无论屏幕大小如何变化。

  • vwvh 的最佳实践:

    • 限制字体大小范围: 使用 calc() 函数结合 vwvh 单位来限制字体大小的变化范围。

      h1 {
        font-size: calc(16px + (5vw - 16px));
        /* 确保字体大小不会小于 16px */
      }
    • 结合 Media Queries 使用: 使用 Media Queries 来针对不同的屏幕尺寸调整 vwvh 单位的值。

    • 考虑用户体验: 避免过度依赖 vwvh 单位,以免影响用户的阅读体验。

第四部分:单位选择的终极指南

说了这么多,到底该选择哪个单位呢? 这里给大家总结一个简单的选择指南:

单位 适用场景 优点 缺点
rem 全局字体大小控制,响应式排版 易于维护,避免嵌套问题,方便实现响应式设计 需要计算,如果根元素字体大小未设置,可能会出现问题
em 局部字体大小调整,组件化设计,需要继承父元素字体大小的场景 方便调整局部字体大小,可以创建具有层次结构的布局,适合组件化设计 嵌套计算复杂,维护困难,当父元素字体大小发生变化时,子元素字体大小会受到影响
vw/vh 全屏布局,响应式视频背景,需要根据视口大小进行调整的场景 简单直观,方便创建与视口大小相关的布局,适合全屏布局 字体大小变化过大,缺乏上下文,可能会导致布局出现问题
px 像素单位,通常用于设置边框、阴影等不需要缩放的元素 精确控制,不会受到其他元素的影响 不利于响应式设计,难以维护

总结:

rememvwvh 都是非常有用的 CSS 单位。 它们各有优缺点,适用于不同的场景。 在实际开发中,我们需要根据具体的需求选择合适的单位,并灵活地结合使用它们,才能创建出高质量的响应式页面。

记住,没有哪个单位是万能的,最重要的是理解它们的特性,并根据实际情况做出最佳选择。

好了,今天的分享就到这里。 希望对大家有所帮助! 如果有什么问题,欢迎随时提问。 祝大家编程愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注