CSS布局技巧 | 豆包MarsCode AI刷题

57 阅读7分钟

CSS相当于网页的血肉,如果没有CSS,网页只能显示内容,但是不够美观,但是要想显示一个足够美观和直观的网页,学会布局是必要的。今天介绍一下浮动、定位、弹性盒子布局,其中部分就以我自己写的网页作为例子,介绍它们的应用场景和实操实践。

浮动 (float)

说实话,在我初学CSS的时候,我还会用浮动实现一些布局,比如说侧边栏,又比如说导航栏左右两侧的内容。但是在学会flexgrid布局之后就很少用了,因为float布局能实现的这两个都能实现,但是float又会有一些问题,因为float之后元素会被移出文档流

float

言归正传,浮动布局是一种经典的CSS布局方式,早期被广泛用于实现多栏布局。元素通过float属性可以在一行内排列,并通过clear属性控制下一行的排列方式。 基本使用

效果
left表明元素必须浮动在其所在的块容器左侧
right表明元素必须浮动在其所在的块容器右侧
none不浮动
inline-start表明元素必须浮动在其所在块容器的开始一侧,在 ltr 脚本中是左侧,在 rtl 脚本中是右侧
inline-start表明元素必须浮动在其所在块容器的结束一侧,在 ltr 脚本中是右侧,在 rtl 脚本中是左侧

说了理论知识,我们来用豆包AI练中学提供的前端环境试一下(父元素无浮动,padding: 10px)
image.png
我们可以发现,第一个元素父元素的高度没了,只剩padding,这就是最开始提到的float的问题之一,高度塌陷,如果一个不浮动的元素的所有子元素都是浮动的,那就没有子元素能撑起父元素的高度。第二个就好多了,因为有一个元素没有浮动,可以撑起父元素高度。
同时我们也能发现,即使左侧浮动了,但是右侧元素仍然会给左侧元素留下位置,并不会被覆盖部分文字

完整代码

<head>
  <meta charset="utf-8" />
  <title>Code Example</title>

  <style>
    * {
      box-sizing: border-box;
    }

    .container {
      width: 100%;
      padding: 10px;
      background-color: darkgreen;
    }

    .sidebar {
      width: 25%;
      background-color: cyan;
      float: left;
    }

    .content {
      width: 75%;
      background-color: yellow;
      float: right;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="sidebar">侧栏(float: left)</div>
    <div class="content">内容(float: right)</div>
  </div>
  <br>
  <br>
  <div class="container">
    <div class="sidebar">浮动左侧</div>
    <div class="normal">普通内容</div>
  </div>
</body>

clear

说到float,不得不提的就是clear,这两个总是一起出现。clear指定一个元素是否必须移动 (清除浮动后) 到在它之前的浮动元素下面。clear 属性适用于浮动和非浮动元素,光说不太直观,我们现在来尝试给之前的代码加上clear: both
然后我们会发现,当clear: both加到containersidebar元素上时,不会有视觉上的差异,但是加到第二个子元素上时
image.png
我们可以发现,两个容器的第二个子元素都跑到了第一个子元素的下方,这也就是前边说的 clear CSS属性指定一个元素是否必须移动 (清除浮动后) 到在它之前的浮动元素下面。clear 属性适用于浮动和非浮动元素。

定位 (position)

position属性用于指定一个元素在文档中的定位方式top bottom left right属性则决定了该元素的最终位置。

取值

position可能的取值有:

  1. static: 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 toprightbottomleft 和 z-index 属性无效。
  2. relative: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relativetable-*-group, table-row, table-column, table-cell, table-caption 元素无效。
  3. absolute: 元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非static定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margin),且不会与其他边距合并。
  4. fixed: 元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transformperspectivefilter 或 backdrop-filter 属性非 none 时,容器由视口改为该祖先。
  5. sticky: 元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和 containing block(最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于 toprightbottom 和 left 的值进行偏移。偏移值不会影响任何其他元素的位置。

基础使用

实际应用

用的最多的就是相对定位和绝对定位了,所以这次拿一个常见的例子做示范,这两个也是相辅相成的,因为绝对定位的元素是以最近的相对定位元素为基准的。

先来看个之前写的模仿Bilibili主页的静态网页

image.png 左侧的下载客户端,包括游戏中心等,在鼠标悬浮时都会显示额外的面板,这个面板就是通过绝对定位实现的,也是很常见的一种设计方式。原理就是父元素(以下称#par)包括正常的内容(以下称#normal),以及一个默认隐藏的要悬浮的元素(以下称#panel),通过设置#parhover事件,来控制#panel的显示,基本原理如下

/* 仅部分代码 */
#par {position: relative;}
#panel {position: absolute; display: none;}
#par:hover #panel {display: block;}

弹性布局 (flex)

这是很常用的单行/单列布局方式,我们先要了解一下基础的知识。
Flex容器(flex container):定义display: flexdisplay: inline-flex的元素就是Flex容器,其子元素称为Flex子项
主轴(main axis)交叉轴(cross axis) :主轴是Flex容器布局的方向,默认是水平的(从左到右),而交叉轴则垂直于主轴。

Flex的常用属性

  • flex-direction:定义主轴方向,控制子元素的排列方式(例如:水平或垂直)。
  • justify-content:控制主轴上的子元素对齐方式(如左对齐、右对齐、居中、分散)。
  • align-itemsalign-content:控制交叉轴上的子元素对齐方式。
  • flex-growflex-shrinkflex-basis:控制子元素在容器中的扩展、收缩和初始大小。

实际应用

1. 一个常见的问题

我们在实际应用flex嵌套时可能会出现子元素过长,导致父元素被撑开显示不正确的问题,原因是flex父元素的最小宽高默认是被内容撑开的,

来看个例子:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Code Example</title>

  <style>
    * {
      box-sizing: border-box;
    }

    .container {
      background-color: green;
      display: flex;
      padding: 10px;
    }

    .child {
      background-color: cyan;
      width: 800px;
    }

    .main {
      display: flex;
      padding: 5px;
      background-color: peru;
    }

    .w400 {
      width: 400px;
    }

    .w800 {
      width: 600px;
    }
  </style>
</head>

<body>
  <div class="container w800">
    <div class="main">
      <div class="w400">我是400px宽度</div>
      <div class="child">asdasdas</div>
    </div>
  </div>
</body>

</html>

image.png 如果将图中开发者工具的min-width启用,那么黄色的main元素就会收到绿色父元素的约束,宽度不会超过绿色的800x

2. 元素居中

在学习布局以前,我们想让一个元素的子元素左右上下都居中,只能通过设置width: auto等复杂的方法,尤其是垂直居中也很困难,但是现在我们只需要

#element {
    display: flex;
    align-items: center;
    justify-content: center;
}

#element的子元素就完全居中了