【实践记录】CSS布局技巧总结 | 豆包MarsCode AI刷题

65 阅读6分钟

从传统的浮动布局到现代化的 flex 与 grid 布局,CSS的布局方式在不断演化,为开发者提供了更强大、更灵活的工具。不同的布局技巧适用于不同的场景,选择合适的布局方式对项目的成功至关重要。本文以实际应用为出发点,介绍浮动布局、定位布局、 flex 、 grid 等常见CSS布局技巧及其实操场景。

浮动布局

float 指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素会脱离标准流,但是仍然保持部分流动性(与绝对定位相反)。浮动的元素会具有行内块元素的特性。

用途

个人认为,浮动布局不应该作为现代网页开发的主要布局方式。首先,根据浮动布局的定义来看,它的最大作用是允许元素被环绕,从而轻松实现图文混排这样的布局,应该只是一种辅助性的布局方式。硬要用浮动做整体网页布局的话,一般做法是先用标准流的块级父元素从上往下排列,之后子元素浮动来排列左右位置,以符合网页布局第一准则。但这个做法存在几个问题:

  • 必须显式指定布局父元素高度。 因为浮动的子元素脱离了标准流,不能靠这些子元素撑开盒子,不清除浮动的话会造成后面的盒子堆叠。虽然有解决方法,给父元素清除浮动就行,但嵌套一多,想理清楚还是很麻烦的,徒增代码维护难度。

  • 复杂布局和响应式布局的实现困难。 浮动不能明确指定子元素在主轴和交叉轴上的排列方式,还需要大量手动计算和代码嵌套,维护体验极差。

就我个人而言,我遇到过用浮动布局的场景就是图文排版,但也用得很少。。

  • 图片环绕文字
    <img class="right-img" src="/images/cover-default.jpg" alt="" srcset="" />
    <p>
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
    </p>
    
    <style>
      .right-img {
          float: right;
          width: 160px;
          height: 100px;
      }
    </style>

image.png

  • 首字大写
    <p class="text">
      <span class="large-start"></span>是一些文本。
      这是一些文本。这是一些文本。 这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
      这是一些文本。这是一些文本。这是一些文本。
    </p>

    <p class="text">
      <span class="large-start">T</span>his is some text. This is some text.
      This is some text. This is some text. This is some text. This is some
      text. This is some text. This is some text. This is some text. This is
      some text. This is some text. This is some text. This is some text. This
      is some text. This is some text. This is some text. This is some text.
      This is some text. This is some text.
    </p>

    <style>
      .text {
        margin-block: 1em;
      }

      .large-start {
        float: left;
        font-size: 2em;
        line-height: 1;
      }
    </style>

image.png

定位布局

position属性用来指定一个元素在网页上的位置,一共有5种定位方式:staticrelativeabsolutestickyfixed

static是默认值。如果省略position,浏览器就认为该元素是static定位。这时,浏览器会按照标准流决定每个元素的位置,这时topbottomleftright四属性(简写为inset,后文为了方便都用这个简写)无效。

relative表示相对于默认位置偏移。

absolute表示相对于最近的非默认定位的父元素进行偏移。所以absolute经常搭配relative使用,限制定位的基准。绝对定位的元素脱离标准流。

fixed表示,相对于视口进行偏移。这会导致元素的位置不随页面滚动而变化,好像固定在网页上一样。

sticky,基于用户的滚动位置来定位,在 relative 与 fixed 之间切换,表现为在跨越特定阈值(inset)前为相对定位,之后为固定定位。

用途

定位布局适合于精确控制元素的位置,比如布局一些右上角的小按钮,显示消息数量的小标签之类的东西。同样不推荐用绝对定位布局网页整体,会带来很多不必要的计算和维护开销。

下面用我的个人博客作为例子(只会给出核心代码):

固定定位用于顶部导航栏

.top-nav {
  position: fixed;
  z-index: 1145;
  @include flex(space-between, center);
  width: 100%;
  height: $nav-h;
  max-width: $scr-w-max;
  padding: 0 12px;
  background-color: color-mix(in oklch, var(--bg-2), transparent 25%);
  transform: translateY(var(--nav-trans-y));
  @include transition((background-color, transform, box-shadow));
}

image.png

粘性定位用于左侧边栏,实现向下滚动时固定一些卡片的位置

主要看 sticky-cards 类。

<template>
  <Transition name="side-card-appear">
    <aside class="side-cards" v-if="mounted">
      <BloggerCard key="side-card-blogger" ref="bloggerCard" />

      <TransitionGroup
        name="card-toggle"
        tag="div"
        class="sticky-cards"
        :style="{
          '--relative-top': relativeTop,
        }"
        @before-leave="setRelativeTop"
        v-if="mounted">
        <section class="info-card" key="side-card-announcement">
          ...
        </section>

        <section
          class="info-card"
          v-if="$route.name !== 'categories'"
          key="side-card-categories">
          ...
        </section>

        <section
          class="info-card"
          v-if="$route.name !== 'tags'"
          key="side-card-tags">
          ...
        </section>
      </TransitionGroup>
    </aside>
  </Transition>
</template>

<script setup lang="ts">
// 省略
</script>

<style lang="scss" scoped>
.side-cards {
  flex-shrink: 0;
  width: $side-card-w;
  @include screenBelow($lg) {
    display: none;
  }
}

.sticky-cards {
  @include flex(null, null, column);
  row-gap: 12px;
  position: sticky;
  top: 12px;
  margin-top: 12px;
}

.info-card {
  @include flex(null, null, column);
  row-gap: 16px;
  width: 100%;
  padding: 20px;
  border-radius: 12px;
  background-color: var(--bg-2);
}

// ...
</style>

<!-- transition -->
<style lang="scss" scoped>
// side-card-appear
// ...

// card-toggle
// ...
</style>

开发环境下的展示:

初始页面 image.png

向下滚动,但固定在"公告"卡片开始的位置: image.png

最终同时触底: image.png

Flex 与 Grid 布局

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。Flex 布局可以简便、完整、响应式地实现各种页面布局。目前所有浏览器都支持 flex 布局,它是未来布局的首选方案。

Grid 布局即网格布局,是一种新的 CSS 布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。号称是最强大的的 CSS 布局方案,是目前唯一一种 CSS 二维布局。

flex 布局和 grid 布局有实质区别,那就是 flex 布局是 一维布局Grid 布局是 二维布局flex 布局一次只能处理一个维度上的元素布局,一行或者一列。Grid 布局是将容器划分成了行和列,产生了一个个网格,我们将网格元素放在与这些行和列相关的位置上来布局。

用途

可以看看我的个人博客仓库:LynnSha1ng/blog: This is my blog built with Vue 3 from scratch.

我的博客许多地方都使用 flex + grid 结合媒体查询实现不同屏幕尺寸下网页排版。下面是开发环境下响应式布局的展示:

image.png

image.png

image.png

image.png

总结与心得

CSS布局技术从传统走向现代化,不仅优化了开发体验,也极大提高了布局的灵活性与适应性。浮动与定位适用于特定场景,Flex 擅长一维布局,而 Grid 布局则是二维布局的首选。在实际项目中,合理组合这些布局技巧是关键。