CSS

一、CSS 基础

1. CSS 选择器及其优先级

CSS 选择器用于定位 HTML 文档中的元素,以便应用样式规则。选择器可以非常简单,也可以相当复杂,具体取决于你想要选择的元素有多特定。下面是一些常见的 CSS 选择器类型:

  1. 元素选择器:直接使用元素名作为选择器。

    p {
      color: blue;
    }
    
  2. 类选择器:使用 . 加上类名来选择具有特定类的所有元素。

    .highlight {
      background-color: yellow;
    }
    
  3. ID 选择器:使用 # 加上 ID 名来选择具有特定 ID 的单个元素。

    #logo {
      font-size: 24px;
    }
    
  4. 属性选择器:基于元素的属性或属性值来选择元素。

    [type="text"] {
      padding: 10px;
    }
    
  5. 伪类选择器:用于定义元素的特殊状态。

    a:hover {
      text-decoration: underline;
    }
    
  6. 伪元素选择器:用于样式化元素的某些部分。

    p::first-line {
      font-weight: bold;
    }
    
  7. 后代选择器:选择某个元素内的所有指定元素。

    div p {
      margin: 0;
    }
    
  8. 子选择器:选择某个元素直接的子元素。

    ul > li {
      list-style: none;
    }
    
  9. 相邻兄弟选择器:选择紧接在另一个元素之后的元素。

    h1 + p {
      font-style: italic;
    }
    
  10. 通用兄弟选择器:选择某元素后的所有同级指定元素。

h1 ~ p {
  color: red;
}

对于选择器的优先级

  • 行内样式 (1000)
  • ID 选择器 (0100)
  • 类选择器、属性选择器和伪类 (0010)
  • 元素选择器和伪元素 (0001)

注意事项:

  • !important 声明的样式的优先级最高;

  • 如果优先级相同,则最后出现的样式生效;

  • 继承得到的样式的优先级最低;

  • 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;

  • 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。

!important 问题

!important 是 CSS 中一个声明,用于提高某个特定样式规则的优先级。当在一条样式规则后面加上 !important 时,这条规则会比其他没有 !important 的规则具有更高的优先级,即使其他规则可能具有更高的特异性(specificity)。

使用 !important 的场景

  1. 覆盖第三方库或框架的样式:当你使用外部库或框架时,可能会遇到需要覆盖其默认样式的场合。
  2. 快速修复:有时候为了快速解决样式问题,开发者可能会临时使用 !important 来确保样式生效。
  3. 内联样式:如果必须覆盖 HTML 中的内联样式,可以使用 !important

使用 !important 可能带来的问题

  1. 维护困难:频繁使用 !important 会导致样式表难以管理和维护。后续开发人员可能很难理解为什么某些样式无法被正常覆盖。
  2. 优先级混乱:它破坏了正常的 CSS 层叠和特异性机制,使得追踪哪些样式正在应用变得复杂。
  3. 难以调试:当多个 !important 规则相互冲突时,确定哪个规则最终生效会变得更加困难。
  4. 灵活性降低:由于 !important 提高了样式规则的优先级,这使得在未来的样式调整中更加困难,因为你需要再次使用 !important 或者增加特异性来覆盖这些样式。

最佳实践

  • 尽量避免使用 !important:首先尝试通过增加选择器的特异性来解决问题。
  • 重构代码:如果发现需要使用 !important,可能是你的 CSS 结构需要优化。考虑是否可以通过更好的组织结构、组件化或其他方式来避免这种情况。
  • 文档记录:如果你确实需要使用 !important,请确保在代码注释中清楚地说明原因,以便其他开发者理解。
  • 工具辅助:一些 CSS 预处理器如 Sass 和 Less 提供了变量、混合宏等特性,可以帮助减少对 !important 的依赖。

总之,虽然 !important 是一个强大的工具,但应该谨慎使用,并且通常只作为最后的手段。正确的做法是保持 CSS 结构清晰,利用合适的特异性和层叠顺序来管理样式。

2. CSS 中可继承与不可继承属性有哪些

在讲继承性之前,我们得知道什么叫继承。用官方一点的话解释说明:

文本相关属性具有继承性,只需要给祖先设置样式,后代所有标签生效。

讲得通俗一点,你肯定听过亲戚朋友跟你说过这样的话:你跟你老爸长得真像,你眼睛真像你老妈。这个就是属于基因里面的继承,你继承了你爸妈的一些相貌特征。你爸妈鼻子很高挺,把你生下来,大概率也会是高鼻梁,这就叫继承,也可以叫遗传。

<div class="div1">
	<ul>
    	<li>1</li>
    	<li>2</li>
    	<li>3</li>
    </ul>
</div>
<style>
   .div1{
       color: red;
   }
</style>
//123显示红色

一、无继承性的属性

  1. display:规定元素应该生成的框的类型
  2. 文本属性
  • vertical-align:垂直文本对齐
  • text-decoration:规定添加到文本的装饰
  • text-shadow:文本阴影效果
  • white-space:空白符的处理
  • unicode-bidi:设置文本的方向
  1. 盒子模型的属性:width、height、margin、border、padding
  2. 背景属性:background、background-color、background-image、background-repeat、background-position、background-attachment
  3. 定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index
  4. 生成内容属性:content、counter-reset、counter-increment
  5. 轮廓样式属性:outline-style、outline-width、outline-color、outline
  6. 页面样式属性:size、page-break-before、page-break-after
  7. 声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during

二、有继承性的属性

  1. 字体系列属性
  • font-family:字体系列
  • font-weight:字体的粗细
  • font-size:字体的大小
  • font-style:字体的风格
  1. 文本系列属性
  • text-indent:文本缩进
  • text-align:文本水平对齐
  • line-height:行高
  • word-spacing:单词之间的间距
  • letter-spacing:中文或者字母之间的间距
  • text-transform:控制文本大小写(就是 uppercase、lowercase、capitalize 这三个)
  • color:文本颜色
  1. 元素可见性
  • visibility:控制元素显示隐藏
  1. 列表布局属性
  • list-style:列表风格,包括 list-style-type、list-style-image 等
  1. 光标属性
  • cursor:光标显示为何种形态
  1. 光标属性
  • cursor:光标显示为何种形态

3. display 的属性值及其作用

属性值作用
none元素不显示,并且会从文档流中移除。
block块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
inline行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
inline-block默认宽度为内容宽度,可以设置宽高,同行显示。
list-item像块类型元素一样显示,并添加样式列表标记。
table此元素会作为块级表格来显示。
inherit规定应该从父元素继承 display 属性的值。

4. display 的 block、inline 和 inline-block 的区别

(1)**block:**会独占一行,多个元素会另起一行,可以设置 width、height、margin 和 padding 属性;

(2)**inline:**元素不会独占一行,设置 width、height 属性无效。但可以设置水平方向的 margin 和 padding 属性,不能设置垂直方向的 padding 和 margin;

(3)**inline-block:**将对象设置为 inline 对象,但对象的内容作为 block 对象呈现,之后的内联对象会被排列在同一行内。

对于行内元素和块级元素,其特点如下:

(1)行内元素

  • 设置宽高无效;
  • 可以设置水平方向的 margin 和 padding 属性,不能设置垂直方向的 padding 和 margin;
  • 不会自动换行;

(2)块级元素

  • 可以设置宽高;
  • 设置 margin 和 padding 都有效;
  • 可以自动换行;
  • 多个块状,默认排列从上到下。

5. 隐藏元素的方法有哪些

  • display: none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。

  • visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。

  • opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。

  • position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。

  • z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。

  • clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

  • transform: scale(0,0):将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

两者都是外部引用 CSS 的方式,它们的区别如下:

  • link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事务;@import 属于 CSS 范畴,只能加载 CSS。
  • link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。
  • link 是 XHTML 标签,无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
  • link 支持使用 Javascript 控制 DOM 去改变样式;而@import 不支持。

7. transition 和 animation 的区别

  • transition 是过渡属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于 flash 的补间动画,设置一个开始关键帧,一个结束关键帧。
  • animation 是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于 flash 的补间动画,但是它可以设置多个关键帧(用@keyframe 定义)完成动画。

8. display:none 与 visibility:hidden 的区别

这两个属性都是让元素隐藏,不可见。两者区别如下:

(1)在渲染树中

  • display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间;
  • visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。

(2)是否是继承属性

  • display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;
  • visibility:hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible可以让子孙节点显示;

(3)修改常规文档流中元素的 display 通常会造成文档的重排,但是修改visibility属性只会造成本元素的重绘;

(4)如果使用读屏器,设置为display:none的内容不会被读取,设置为visibility:hidden的内容会被读取。

9. 伪元素和伪类的区别和作用?

  • 伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:
p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}

  • 伪类:将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。例如:
a:hover {color: #FF00FF}
p:first-child {color: red}

**总结:**伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。

10. 对 requestAnimationframe 的理解

实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout 来实现,CSS3 中可以使用 transition 和 animation 来实现,HTML5 中的 canvas 也可以实现。除此之外,HTML5 提供一个专门用于请求动画的 API,那就是 requestAnimationFrame,顾名思义就是请求动画帧

MDN 对该方法的描述:

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

语法: window.requestAnimationFrame(callback); 其中,callback 是下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入 DOMHighResTimeStamp 参数,它表示 requestAnimationFrame() 开始去执行回调函数的时刻。该方法属于宏任务,所以会在执行完微任务之后再去执行。

**取消动画:**使用 cancelAnimationFrame()来取消执行动画,该方法接收一个参数——requestAnimationFrame 默认返回的 id,只需要传入这个 id 就可以取消动画了。

优势:

  • CPU 节能:使用 SetTinterval 实现的动画,当页面被隐藏或最小化时,SetTinterval 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费 CPU 资源。而 RequestAnimationFrame 则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统走的 RequestAnimationFrame 也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了 CPU 开销。
  • 函数节流:在高频率事件( resize, scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,RequestAnimationFrame 可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销,一个刷新间隔内函数执行多次时没有意义的,因为多数显示器每 16.7ms 刷新一次,多次绘制并不会在屏幕上体现出来。
  • 减少 DOM 操作:requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒 60 帧。

setTimeout 执行动画的缺点:它通过设定间隔时间来不断改变图像位置,达到动画效果。但是容易出现卡顿、抖动的现象;原因是:

  • settimeout 任务被放入异步队列,只有当主线程任务执行完后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;
  • settimeout 的固定时间间隔不一定与屏幕刷新间隔时间相同,会引起丢帧。

11. 对盒模型的理解

CSS3 中的盒模型有以下两种:标准盒子模型、IE 盒子模型

img

img

CSS3中的盒模型有以下两种:标准盒模型、IE盒模型

盒模型都是由四个部分组成的,分别是margin、padding、border和content

标准盒模型和iE盒模型的区别:

在于设置width和height时,所对应的范围不同

标准盒模型的width和height属性的范围只包含了content IE盒模型的width和height属性的范围包含了border padding 和content

可以通过修改元素的box-sizing属性来改变元素的盒模型: box-sizing:content-box表示标准盒模型(默认值) box-sizing:border-box表示IE盒子模型(怪异盒模型)

12. 为什么有时候⽤translate来改变位置⽽不是定位?

translate 是 transform 属性的⼀个值。改变 transform 或 opacity 不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform 使浏览器为元素创建⼀个 GPU 图层,但改变绝对定位会使⽤到 CPU。 因此 translate()更⾼效,可以缩短平滑动画的绘制时间。 ⽽ translate 改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况。

13. li 与 li 之间有看不见的空白间隔是什么原因引起的?如何解决?

浏览器会把 inline 内联元素间的空白字符(空格、换行、Tab 等)渲染成一个空格。为了美观,通常是一个<li>放在一行,这导致<li>换行后产生换行字符,它变成一个空格,占用了一个字符的宽度。

解决办法:

(1)为<li>设置 float:left。不足:有些容器是不能设置浮动,如左右切换的焦点图等。

(2)将所有<li>写在同一行。不足:代码不美观。

(3)将<ul>内的字符尺寸直接设为 0,即 font-size:0。不足:<ul>中的其他字符尺寸也被设为 0,需要额外重新设定其他字符尺寸,且在 Safari 浏览器依然会出现空白间隔。

(4)消除<ul>的字符间隔 letter-spacing:-8px,不足:这也设置了<li>内的字符间隔,因此需要将<li>内的字符间隔设为默认 letter-spacing:normal。

14. CSS3 中有哪些新特性

  • 新增各种 CSS 选择器 (: not(.input):所有 class 不是“input”的节点)
  • 圆角 (border-radius:8px)
  • 多列布局 (multi-column layout)
  • 阴影和反射 (Shadoweflect)
  • 文字特效 (text-shadow)
  • 文字渲染 (Text-decoration)
  • 线性渐变 (gradient)
  • 旋转 (transform)
  • 增加了旋转,缩放,定位,倾斜,动画,多背景

15. 替换元素的概念及计算规则

通过修改某个属性值呈现的内容就可以被替换的元素就称为“替换元素”。

替换元素除了内容可替换这一特性以外,还有以下特性:

  • 内容的外观不受页面上的 CSS 的影响:用专业的话讲就是在样式表现在 CSS 作用域之外。如何更改替换元素本身的外观需要类似 appearance 属性,或者浏览器自身暴露的一些样式接口。
  • 有自己的尺寸:在 Web 中,很多替换元素在没有明确尺寸设定的情况下,其默认的尺寸(不包括边框)是 300 像素 ×150 像素,如
  • 在很多 CSS 属性上有自己的一套表现规则:比较具有代表性的就是 vertical-align 属性,对于替换元素和非替换元素,vertical-align 属性值的解释是不一样的。比方说 vertical-align 的默认值的 baseline,很简单的属性值,基线之意,被定义为字符 x 的下边缘,而替换元素的基线却被硬生生定义成了元素的下边缘。
  • 所有的替换元素都是内联水平元素:也就是替换元素和替换元素、替换元素和文字都是可以在一行显示的。但是,替换元素默认的 display 值却是不一样的,有的是 inline,有的是 inline-block。

替换元素的尺寸从内而外分为三类:

  • 固有尺寸: 指的是替换内容原本的尺寸。例如,图片、视频作为一个独立文件存在的时候,都是有着自己的宽度和高度的。
  • HTML 尺寸: 只能通过 HTML 原生属性改变,这些 HTML 原生属性包括的 width 和 height 属性、的 size 属性。
  • CSS 尺寸: 特指可以通过 CSS 的 width 和 height 或者 max-width/min-width 和 max-height/min-height 设置的尺寸,对应盒尺寸中的 content box。

这三层结构的计算规则具体如下:

(1)如果没有 CSS 尺寸和 HTML 尺寸,则使用固有尺寸作为最终的宽高。

(2)如果没有 CSS 尺寸,则使用 HTML 尺寸作为最终的宽高。

(3)如果有 CSS 尺寸,则最终尺寸由 CSS 属性决定。

(4)如果“固有尺寸”含有固有的宽高比例,同时仅设置了宽度或仅设置了高度,则元素依然按照固有的宽高比例显示。

(5)如果上面的条件都不符合,则最终宽度表现为 300 像素,高度为 150 像素。

(6)内联替换元素和块级替换元素使用上面同一套尺寸计算规则。

16. 常见的图片格式及使用场景

(1)BMP,是无损的、既支持索引色也支持直接色的点阵图。这种图片格式几乎没有对数据进行压缩,所以 BMP 格式的图片通常是较大的文件。

(2)GIF是无损的、采用索引色的点阵图。采用 LZW 压缩算法进行编码。文件小,是 GIF 格式的优点,同时,GIF 格式还具有支持动画以及透明的优点。但是 GIF 格式仅支持 8bit 的索引色,所以 GIF 格式适用于对色彩要求不高同时需要文件体积较小的场景。

(3)JPEG是有损的、采用直接色的点阵图。JPEG 的图片的优点是采用了直接色,得益于更丰富的色彩,JPEG 非常适合用来存储照片,与 GIF 相比,JPEG 不适合用来存储企业 Logo、线框类的图。因为有损压缩会导致图片模糊,而直接色的选用,又会导致图片文件较 GIF 更大。

(4)PNG-8是无损的、使用索引色的点阵图。PNG 是一种比较新的图片格式,PNG-8 是非常好的 GIF 格式替代者,在可能的情况下,应该尽可能的使用 PNG-8 而不是 GIF,因为在相同的图片效果下,PNG-8 具有更小的文件体积。除此之外,PNG-8 还支持透明度的调节,而 GIF 并不支持。除非需要动画的支持,否则没有理由使用 GIF 而不是 PNG-8。

(5)PNG-24是无损的、使用直接色的点阵图。PNG-24 的优点在于它压缩了图片的数据,使得同样效果的图片,PNG-24 格式的文件大小要比 BMP 小得多。当然,PNG24 的图片还是要比 JPEG、GIF、PNG-8 大得多。

(6)SVG是无损的矢量图。SVG 是矢量图意味着 SVG 图片由直线和曲线以及绘制它们的方法组成。当放大 SVG 图片时,看到的还是线和曲线,而不会出现像素点。SVG 图片在放大时,不会失真,所以它适合用来绘制 Logo、Icon 等。

(7)WebP是谷歌开发的一种新图片格式,WebP 是同时支持有损和无损压缩的、使用直接色的点阵图。从名字就可以看出来它是为 Web 而生的,什么叫为 Web 而生呢?就是说相同质量的图片,WebP 具有更小的文件体积。现在网站上充满了大量的图片,如果能够降低每一个图片的文件大小,那么将大大减少浏览器和服务器之间的数据传输量,进而降低访问延迟,提升访问体验。目前只有 Chrome 浏览器和 Opera 浏览器支持 WebP 格式,兼容性不太好。

  • 在无损压缩的情况下,相同质量的 WebP 图片,文件大小要比 PNG 小 26%;
  • 在有损压缩的情况下,具有相同图片精度的 WebP 图片,文件大小要比 JPEG 小 25%~34%;
  • WebP 图片格式支持图片透明度,一个无损压缩的 WebP 图片,如果要支持透明度只需要 22%的格外文件大小。

17. 对 CSSSprites 的理解

CSSSprites(精灵图),将一个页面涉及到的所有图片都包含到一张大图中去,然后利用 CSS 的 background-image,background-repeat,background-position 属性的组合进行背景定位。

优点:

  • 利用CSS Sprites能很好地减少网页的 http 请求,从而大大提高了页面的性能,这是CSS Sprites最大的优点;
  • CSS Sprites能减少图片的字节,把 3 张图片合并成 1 张图片的字节总是小于这 3 张图片的字节总和。

缺点:

  • 在图片合并时,要把多张图片有序的、合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景。在宽屏及高分辨率下的自适应页面,如果背景不够宽,很容易出现背景断裂;
  • CSSSprites在开发的时候相对来说有点麻烦,需要借助photoshop或其他工具来对每个背景单元测量其准确的位置。
  • 维护方面:CSS Sprites在维护的时候比较麻烦,页面背景有少许改动时,就要改这张合并的图片,无需改的地方尽量不要动,这样避免改动更多的CSS,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动CSS

18. 什么是物理像素,逻辑像素和像素密度,为什么在移动端开发时需要用到@3x, @2x 这种图片?

以 iPhone XS 为例,当写 CSS 代码时,针对于单位 px,其宽度为 414px & 896px,也就是说当赋予一个 DIV 元素宽度为 414px,这个 DIV 就会填满手机的宽度;

而如果有一把尺子来实际测量这部手机的物理像素,实际为 1242*2688 物理像素;经过计算可知,1242/414=3,也就是说,在单边上,一个逻辑像素=3 个物理像素,就说这个屏幕的像素密度为 3,也就是常说的 3 倍屏。

对于图片来说,为了保证其不失真,1 个图片像素至少要对应一个物理像素,假如原始图片是 500*300 像素,那么在 3 倍屏上就要放一个 1500900 像素的图片才能保证 1 个物理像素至少对应一个图片像素,才能不失真。

img

当然,也可以针对所有屏幕,都只提供最高清图片。虽然低密度屏幕用不到那么多图片像素,而且会因为下载多余的像素造成带宽浪费和下载延迟,但从结果上说能保证图片在所有屏幕上都不会失真。

还可以使用 CSS 媒体查询来判断不同的像素密度,从而选择不同的图片:

my-image { background: (low.png); }
@media only screen and (min-device-pixel-ratio: 1.5) {
  #my-image { background: (high.png); }
}

19. margin 和 padding 的使用场景

  • 需要在 border 外侧添加空白,且空白处不需要背景(色)时,使用 margin;
  • 需要在 border 内测添加空白,且空白处需要背景(色)时,使用 padding。

20. 对line-height 的理解及其赋值方式

(1)line-height 的概念:

  • line-height 指一行文本的高度,包含了字间距,实际上是下一行基线到上一行基线距离;
  • 如果一个标签没有定义 height 属性,那么其最终表现的高度由 line-height 决定;
  • 一个容器没有设置高度,那么撑开容器高度的是 line-height,而不是容器内的文本内容;
  • 把 line-height 值设置为 height 一样大小的值可以实现单行文字的垂直居中;
  • line-height 和 height 都能撑开一个高度;

(2)line-height 的赋值方式:

  • 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高
  • 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px
  • 百分比:将计算后的值传递给后代

21. CSS 优化和提高性能的方法有哪些?

加载性能:

(1)css 压缩:将写好的 css 进行打包压缩,可以减小文件体积。

(2)css 单一样式:当需要下边距和左边距的时候,很多时候会选择使用 margin:top 0 bottom 0;但 margin-bottom:bottom;margin-left:left;执行效率会更高。

(3)减少使用@import,建议使用 link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。

选择器性能:

(1)关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分)。CSS 选择符是从右到左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等;

(2)如果规则拥有 ID 选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了)。

(3)避免使用通配规则,如*{}计算次数惊人,只对需要用到的元素进行选择。

(4)尽量少的去对标签进行选择,而是用 class。

(5)尽量少的去使用后代选择器,降低选择器的权重值。后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素。

(6)了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。

渲染性能:

(1)慎重使用高性能属性:浮动、定位。

(2)尽量减少页面重排、重绘。

(3)去除空规则:{}。空规则的产生原因一般来说是为了预留样式。去除这些空规则无疑能减少 css 文档体积。

(4)属性值为 0 时,不加单位。

(5)属性值为浮动小数 0.**,可以省略小数点之前的 0。

(6)标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后。

(7)不使用@import 前缀,它会影响 css 的加载速度。

(8)选择器优化嵌套,尽量避免层级过深。

(9)css 雪碧图,同一页面相近部分的小图标,方便使用,减少页面的请求次数,但是同时图片本身会变大,使用时,优劣考虑清楚,再使用。

(10)正确使用 display 的属性,由于 display 的作用,某些样式组合会无效,徒增样式体积的同时也影响解析性能。

(11)不滥用 web 字体。对于中文网站来说 WebFonts 可能很陌生,国外却很流行。web fonts 通常体积庞大,而且一些浏览器在下载 web fonts 时会阻塞页面渲染损伤性能。

可维护性、健壮性:

(1)将具有相同属性的样式抽离出来,整合并通过 class 在页面中进行使用,提高 css 的可维护性。

(2)样式与内容分离:将 css 代码定义到外部 css 中。

22. CSS 预处理器/后处理器是什么?为什么要使用它们?

**预处理器,**如:lesssassstylus,用来预编译sass或者less,增加了css代码的复用性。层级,mixin, 变量,循环, 函数等对编写以及开发 UI 组件都极为方便。

后处理器, 如: postCss,通常是在完成的样式表中根据css规范处理css,让其更加有效。目前最常做的是给css属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。

css预处理器为css增加一些编程特性,无需考虑浏览器的兼容问题,可以在CSS中使用变量,简单的逻辑程序,函数等在编程语言中的一些基本的性能,可以让css更加的简洁,增加适应性以及可读性,可维护性等。

其它css预处理器语言:Sass(Scss), Less, Stylus, Turbine, Swithch css, CSS Cacheer, DT Css

使用原因:

  • 结构清晰, 便于扩展
  • 可以很方便的屏蔽浏览器私有语法的差异
  • 可以轻松实现多重继承
  • 完美的兼容了CSS代码,可以应用到老项目中

23. ::before 和 :after 的双冒号和单冒号有什么区别?

(1)冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。

(2)::before就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素。并不存在于dom之中,只存在在页面之中。

注意: :before :after 这两个伪元素,是在CSS2.1里新出现的。起初,伪元素的前缀使用的是单冒号语法,但随着Web的进化,在CSS3的规范里,伪元素的语法被修改成使用双冒号,成为::before::after

24. display:inline-block 什么时候会显示间隙?

  • 有空格时会有间隙,可以删除空格解决;
  • margin正值时,可以让margin使用负值解决;
  • 使用font-size时,可通过设置font-size:0letter-spacingword-spacing解决;

25. 单行、多行文本溢出隐藏

  • 单行文本溢出
overflow: hidden;            // 溢出隐藏
text-overflow: ellipsis;     // 溢出用省略号显示
white-space: nowrap;         // 规定段落中的文本不进行换行
  • 多行文本溢出
overflow: hidden;            // 溢出隐藏
text-overflow: ellipsis;     // 溢出用省略号显示
display:-webkit-box;         // 作为弹性伸缩盒子模型显示。
-webkit-box-orient:vertical; // 设置伸缩盒子的子元素排列方式:从上到下垂直排列
-webkit-line-clamp:3;        // 显示的行数

注意:由于上面的三个属性都是 CSS3 的属性,没有浏览器可以兼容,所以要在前面加一个-webkit- 来兼容一部分浏览器。

26. Sass、Less 是什么?为什么要使用他们?

他们都是 CSS 预处理器,是 CSS 上的一种抽象层。他们是一种特殊的语法/语言编译成 CSS。 例如 Less 是一种动态样式语言,将 CSS 赋予了动态语言的特性,如变量,继承,运算, 函数,LESS 既可以在客户端上运行 (支持 IE 6+, Webkit, Firefox),也可以在服务端运行 (借助 Node.js)。

为什么要使用它们?

  • 结构清晰,便于扩展。 可以方便地屏蔽浏览器私有语法差异。封装对浏览器语法差异的重复处理, 减少无意义的机械劳动。
  • 可以轻松实现多重继承。 完全兼容 CSS 代码,可以方便地应用到老项目中。LESS 只是在 CSS 语法上做了扩展,所以老的 CSS 代码也可以与 LESS 代码一同编译。

27. 对媒体查询的理解?

媒体查询由⼀个可选的媒体类型和零个或多个使⽤媒体功能的限制了样式表范围的表达式组成,例如宽度、⾼度和颜⾊。媒体查询,添加⾃ CSS3,允许内容的呈现针对⼀个特定范围的输出设备⽽进⾏裁剪,⽽不必改变内容本身,适合 web ⽹⻚应对不同型号的设备⽽做出对应的响应适配。

媒体查询包含⼀个可选的媒体类型和满⾜ CSS3 规范的条件下,包含零个或多个表达式,这些表达式描述了媒体特征,最终会被解析为 true 或 false。如果媒体查询中指定的媒体类型匹配展示⽂档所使⽤的设备类型,并且所有的表达式的值都是 true,那么该媒体查询的结果为 true。那么媒体查询内的样式将会⽣效。

<!-- link元素中的CSS媒体查询 -->
<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
<!-- 样式表中的CSS媒体查询 -->
<style>
@media (max-width: 600px) {
  .facet_sidebar {
    display: none;
  }
}
</style>

简单来说,使用 @media 查询,可以针对不同的媒体类型定义不同的样式。@media 可以针对不同的屏幕尺寸设置不同的样式,特别是需要设置设计响应式的页面,@media 是非常有用的。当重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。

28. 对 CSS 工程化的理解

CSS工程化是指通过一系列方法、工具和技术来组织、管理和优化CSS代码,以适应大型项目的复杂性,并提高开发效率、可维护性和团队协作能力。它关注于如何更好地设计、编码、构建和维护CSS,使得在项目规模增长时仍能保持高效和高质量的输出。以下是几个关键方面,它们共同构成了对CSS工程化的理解:

1. 模块化

  • 组件化:将样式按照功能或页面组件进行划分,每个组件都有独立的样式文件,这有助于复用和维护。
  • 命名规范:采用一致且清晰的命名规则,如BEM(Block Element Modifier)命名法,可以减少类名冲突并提高代码的可读性。

2. 预处理器

  • Sass/SCSS, Less, Stylus:预处理器提供了变量、嵌套、混合、函数等高级特性,使CSS编写更加灵活且易于管理。
  • 编译与自动化:利用Gulp、Webpack或其他构建工具自动编译预处理语言到标准CSS,并执行其他优化任务如压缩、添加浏览器前缀等。

3. 工程化插件

  • PostCSS:PostCSS是一个使用JavaScript插件转换CSS的工具,可以实现自动添加浏览器前缀、支持未来CSS语法等功能。
  • Autoprefixer:一个流行的PostCSS插件,自动为CSS规则添加必要的浏览器前缀。

4. 构建与打包

  • Webpack:使用css-loaderstyle-loader等加载器来处理CSS模块,确保样式可以被正确地导入、解析和插入到HTML中。
  • Code Splitting:按需加载CSS,只加载当前页面所需的样式,从而提升性能。

5. 可维护性

  • 文档与注释:良好的文档和适当的注释对于后期维护至关重要,帮助新加入团队的成员快速理解现有代码。
  • 版本控制:使用Git等版本控制系统记录每次变更,便于追踪问题和回滚。

6. 性能优化

  • 压缩与清理:使用工具如PurgeCSS移除未使用的CSS规则,减少最终打包后的文件大小。
  • 响应式设计:利用媒体查询创建适应不同屏幕尺寸的设计,同时保证移动优先的原则。

7. CSS-in-JS

  • styled-components, emotion:这些库允许直接在JavaScript中定义样式,提供局部作用域和动态样式的能力,适合React等现代前端框架的应用。

8. 测试

  • 视觉回归测试:使用BackstopJS或Percy等工具对比界面变化,确保样式更新不会意外破坏布局。
  • 单元测试:对于CSS-in-JS或JavaScript控制样式的部分,可以编写单元测试来验证行为一致性。

9. 设计系统

  • Style Guide:建立一套统一的设计指南,包括颜色、字体、间距等基础元素,以及按钮、表单等UI组件的标准样式。
  • Storybook:用于展示和测试UI组件的环境,方便开发者和设计师协作,确保组件的一致性和质量。

10. 最佳实践

  • 避免全局污染:尽可能限制样式的作用范围,比如使用CSS Modules或局部作用域。
  • 遵循语义化原则:选择有意义的类名和ID,避免使用过于通用或含义模糊的选择器。

通过上述方法和技术的应用,CSS工程化不仅解决了传统CSS开发中的许多痛点,还促进了更好的团队合作和更高效的开发流程。随着Web应用越来越复杂,CSS工程化的重要性愈发凸显,成为现代前端开发不可或缺的一部分。

CSS 工程化是为了解决以下问题:

  1. 宏观设计:CSS 代码如何组织、如何拆分、模块结构怎样设计?
  2. 编码优化:怎样写出更好的 CSS?
  3. 构建:如何处理我的 CSS,才能让它的打包结果最优?
  4. 可维护性:代码写完了,如何最小化它后续的变更成本?如何确保任何一个同事都能轻松接手?

以下三个方向都是时下比较流行的、普适性非常好的 CSS 工程化实践:

  • 预处理器:Less、 Sass 等;
  • 重要的工程化插件: PostCss;
  • Webpack loader 等 。

基于这三个方向,可以衍生出一些具有典型意义的子问题,这里我们逐个来看:

(1)预处理器:为什么要用预处理器?它的出现是为了解决什么问题?

预处理器,其实就是 CSS 世界的“轮子”。预处理器支持我们写一种类似 CSS、但实际并不是 CSS 的语言,然后把它编译成 CSS 代码:

img

那为什么写 CSS 代码写得好好的,偏偏要转去写“类 CSS”呢?这就和本来用 JS 也可以实现所有功能,但最后却写 React 的 jsx 或者 Vue 的模板语法一样——为了爽!要想知道有了预处理器有多爽,首先要知道的是传统 CSS 有多不爽。随着前端业务复杂度的提高,前端工程中对 CSS 提出了以下的诉求:

  1. 宏观设计上:我们希望能优化 CSS 文件的目录结构,对现有的 CSS 文件实现复用;
  2. 编码优化上:我们希望能写出结构清晰、简明易懂的 CSS,需要它具有一目了然的嵌套层级关系,而不是无差别的一铺到底写法;我们希望它具有变量特征、计算能力、循环能力等等更强的可编程性,这样我们可以少写一些无用的代码;
  3. 可维护性上:更强的可编程性意味着更优质的代码结构,实现复用意味着更简单的目录结构和更强的拓展能力,这两点如果能做到,自然会带来更强的可维护性。

这三点是传统 CSS 所做不到的,也正是预处理器所解决掉的问题。预处理器普遍会具备这样的特性:

  • 嵌套代码的能力,通过嵌套来反映不同 css 属性之间的层级关系 ;
  • 支持定义 css 变量;
  • 提供计算函数;
  • 允许对代码片段进行 extend 和 mixin;
  • 支持循环语句的使用;
  • 支持将 CSS 文件模块化,实现复用。

(2)PostCss:PostCss 是如何工作的?我们在什么场景下会使用 PostCss?

PostCss 仍然是一个对 CSS 进行解析和处理的工具,它会对 CSS 做这样的事情:

img

它和预处理器的不同就在于,预处理器处理的是 类 CSS,而 PostCss 处理的就是 CSS 本身。Babel 可以将高版本的 JS 代码转换为低版本的 JS 代码。PostCss 做的是类似的事情:它可以编译尚未被浏览器广泛支持的先进的 CSS 语法,还可以自动为一些需要额外兼容的语法增加前缀。更强的是,由于 PostCss 有着强大的插件机制,支持各种各样的扩展,极大地强化了 CSS 的能力。

PostCss 在业务中的使用场景非常多:

  • 提高 CSS 代码的可读性:PostCss 其实可以做类似预处理器能做的工作;
  • 当我们的 CSS 代码需要适配低版本浏览器时,PostCss 的 Autoprefixeropen in new window 插件可以帮助我们自动增加浏览器前缀;
  • 允许我们编写面向未来的 CSS:PostCss 能够帮助我们编译 CSS next 代码;

(3)Webpack 能处理 CSS 吗?如何实现?

Webpack 能处理 CSS 吗:

  • Webpack 在裸奔的状态下,是不能处理 CSS 的,Webpack 本身是一个面向 JavaScript 且只能处理 JavaScript 代码的模块化打包工具;
  • Webpack 在 loader 的辅助下,是可以处理 CSS 的。

如何用 Webpack 实现对 CSS 的处理:

  • Webpack 中操作 CSS 需要使用的两个关键的 loader:css-loader 和 style-loader
  • 注意,答出“用什么”有时候可能还不够,面试官会怀疑你是不是在背答案,所以你还需要了解每个 loader 都做了什么事情:
    • css-loader:导入 CSS 模块,对 CSS 代码进行编译处理;
    • style-loader:创建 style 标签,把 CSS 内容写入标签。

在实际使用中,css-loader 的执行顺序一定要安排在 style-loader 的前面。因为只有完成了编译过程,才可以对 css 代码进行插入;若提前插入了未编译的代码,那么 webpack 是无法理解这坨东西的,它会无情报错。

29. 如何判断元素是否到达可视区域

以图片显示为例:

  • window.innerHeight 是浏览器可视区的高度;
  • document.body.scrollTop || document.documentElement.scrollTop 是浏览器滚动的过的距离;
  • imgs.offsetTop 是元素顶部距离文档顶部的高度(包括滚动条的距离);
  • 内容达到显示区域的:img.offsetTop < window.innerHeight + document.body.scrollTop;

img

30. z-index 属性在什么情况下会失效

通常 z-index 的使用是在有两个重叠的标签,在一定的情况下控制其中一个在另一个的上方或者下方出现。z-index 值越大就越是在上层。z-index 元素的 position 属性需要是 relative,absolute 或是 fixed。

z-index 属性在下列情况下会失效:

  • 父元素 position 为 relative 时,子元素的 z-index 失效。解决:父元素 position 改为 absolute 或 static;
  • 元素没有设置 position 属性为非 static 属性。解决:设置该元素的 position 属性为 relative,absolute 或是 fixed 中的一种;
  • 元素在设置 z-index 的同时还设置了 float 浮动。解决:float 去除,改为 display:inline-block;

31.css 如何获取标签的内部的第一个元素

在CSS中,直接通过选择器来获取某个标签内部的第一个子元素是有限制的,因为CSS选择器主要是用来选择元素而不是直接访问元素的子元素顺序。但是,你可以使用特定的伪类和选择器组合来达到这个目的。

对于获取一个标签(我们称之为父元素)内部的第一个子元素,你可以使用:first-child伪类或:first-of-type伪类(取决于你的具体需求)。

使用 :first-child

:first-child 选择器用于选择属于其父元素的第一个子元素的每个元素。

css复制代码

.parent > :first-child {  
    /* 样式 */  
}

这里的.parent > :first-child会选中.parent类元素下的第一个直接子元素,无论这个子元素是什么类型。

使用 :first-of-type

:first-of-type 选择器用于选择属于其父元素下相同类型元素中的第一个元素。

css复制代码

.parent > *:first-of-type {  
    /* 样式 */  
}

但是,请注意,直接使用*作为选择器可能不是最高效的做法,因为这会匹配所有类型的元素。如果你知道第一个子元素的类型(比如<p><div>),最好直接指定那个类型:

css复制代码

.parent > p:first-of-type {  
    /* 样式 */  
}

这会选择.parent类元素下的第一个<p>子元素。

注意

  • :first-child:first-of-type的区别在于,:first-child只考虑元素的顺序,而不考虑元素的类型,而:first-of-type则是考虑相同类型元素中的第一个。
  • 如果你需要选择特定类型的第一个子元素,且该元素前面可能有其他类型的元素,那么:first-of-type可能是更好的选择。
  • 在某些情况下,如果父元素只有一个子元素,那么这个子元素既是:first-child也是:last-child,同时可能也是:only-child

32.css基本数据类型有哪些

css基本数据类型有数值类型、颜色类型、字符串类型、标识符类型、url类型、数字类型、百分比类型、布尔类型和自定义数据类型。

1、数值类型:包括长度单位和百分比。长度单位有像素(px)、点(pt)、英寸(in)、厘米(cm)、毫米(mm)等。百分比用于相对于父元素的长度或宽度。

2、颜色类型:包括十六进制颜色值(#RRGGBB)、RGB颜色值(rgb(red, green, blue))、RGBA颜色值(rgba(red, green, blue, alpha))、HSL颜色值(hsl(hue, saturation, lightness))和HSLA颜色值(hsla(hue, saturation, lightness, alpha))。

3、字符串类型:用于描述文本、字体名称等。字符串需用引号包裹,如'Arial', "Helvetica Neue", sans-serif。

4、标识符类型:用于描述CSS属性值的标识符,例如font-family中的字体名称。

5、URL类型:用于引用外部资源。例如,background-image属性中可以使用url()来引用背景图片的URL。

6、数字类型:用于表示数值,可以包括整数或小数。

7、百分比类型:用于设置相对长度的数值,通常表示相对于父元素的百分比。

8、布尔类型:表示真或假,如visible和hidden。

9、自定义数据类型:用户可以自定义一些数据类型,例如自定义属性值。

33. flex 可以使用定位吗?

可以

34. flex 内使用相对定位有效果吗

二、页面布局

1. 常见的 CSS 布局单位

常用的布局单位包括像素(px),百分比(%),emremvw/vh

(1)像素px)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS 像素和物理像素:

  • CSS 像素:为 web 开发者提供,在 CSS 中使用的一个抽象单位;
  • 物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。

(2)百分比%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。

(3)em 和 rem相对于 px 更具灵活性,它们都是相对长度单位,它们之间的区别:em 相对于父元素,rem 相对于根元素。

  • em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认 16px)。(相对父元素的字体大小倍数)。
  • rem: rem 是 CSS3 新增的一个相对单位,相对于根元素(html 元素)的 font-size 的倍数。作用:利用 rem 可以实现简单的响应式布局,可以利用 html 元素中字体的大小与屏幕间的比值来设置 font-size 的值,以此实现当屏幕分辨率变化时让元素也随之变化。

(4)vw/vh是与视图窗口有关的单位,vw 表示相对于视图窗口的宽度,vh 表示相对于视图窗口高度,除了 vw 和 vh 外,还有 vmin 和 vmax 两个相关的单位。

  • vw:相对于视窗的宽度,视窗宽度是 100vw;
  • vh:相对于视窗的高度,视窗高度是 100vh;
  • vmin:vw 和 vh 中的较小值;
  • vmax:vw 和 vh 中的较大值;

vw/vh 和百分比很类似,两者的区别:

  • 百分比(%):大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate 等)
  • vw/vm:相对于视窗的尺寸

2. px、em、rem 的区别及使用场景

emrem 都是CSS中的相对长度单位,但它们的参考点不同,这导致了它们在实际应用中的行为和使用场景也有所不同。

rem是根据html根节点来计算的,而em是根据父级元素的字体计算的。

  • rem单位相对于根元素的html字体大小,大多数浏览器的默认字体大小是 16px,而em单位相对于父元素的字体大小。这意味着使用rem单位可以更方便地实现响应式设计,因为只需要在根元素上设置字体大小即可影响整个页面的尺寸,而em单位则需要考虑父元素的字体大小。
  • rem单位相对于根元素的字体大小是固定的,不会受到父元素字体大小的影响。而em单位会受到父元素字体大小的影响,如果父元素的字体大小改变,那么em单位的计算结果也会改变。
  • 使用rem单位时,可以更方便地进行单位换算,因为rem单位是相对于根元素的字体大小的倍数,而根元素的字体大小通常是以px为单位的。而em单位则需要根据父元素的字体大小来计算,换算起来相对复杂一些。
  • rem单位更适合用于响应式设计,而em单位更适合用于局部尺寸的调整。

em 单位

  • 定义em 是一个相对单位,它的值相对于当前元素的字体大小计算得出。

    • 对于字体大小(font-size),em 指的是当前元素的字体大小。
    • 对于其他尺寸(如边距、内边距等),em 指的是当前元素父元素的字体大小。
  • 特点

    • 可缩放性:由于 em 是相对于当前元素或其父元素的字体大小,因此它可以实现尺寸的自动缩放。
    • 继承性em 单位可以继承父元素的字体大小变化,使得布局更加灵活。
  • 示例

    body {
      font-size: 16px; /* 基准字体大小 */
    }
    p {
      font-size: 1.25em; /* 相对于body的字体大小,即20px (16 * 1.25) */
    }
    .container {
      margin: 2em; /* 相对于父元素的字体大小 */
      padding: 1em; /* 相对于自身字体大小 */
    }
    
  • 潜在问题

    • 在多层嵌套的情况下,em 的计算可能会变得复杂。因为每一层都可能有自己独立的字体大小设置,这会导致比例关系变得难以预测和控制。
    • 如果不小心,可能会出现比例混乱的情况,尤其是在深度嵌套的结构中。

rem 单位

  • 定义rem 也是一个相对单位,但它总是相对于根元素(通常是 <html> 标记)的字体大小计算得出。

  • 特点

    • 全局一致性:由于 rem 始终相对于根元素的字体大小,因此在整个页面中保持了一致性。
    • 易于维护:通过设置根元素的字体大小,可以很容易地调整整个页面的字体大小和其他尺寸。
  • 示例

    html {
      font-size: 16px; /* 基准字体大小 */
    }
    p {
      font-size: 1.25rem; /* 相对于html的字体大小,即20px (16 * 1.25) */
    }
    .container {
      margin: 2rem; /* 相对于html的字体大小 */
      padding: 1rem; /* 相对于html的字体大小 */
    }
    
  • 优点

    • rem 可以避免 em 在多层嵌套时可能出现的比例混乱问题。
    • 通过修改根元素的字体大小,可以轻松实现整个页面的响应式调整。

如何选择

  • 使用 em
    • 当你需要创建基于当前元素或其直接父元素的相对尺寸时,例如按钮内的文本和图标之间的间距。
    • 当你希望某个组件根据其父容器的大小进行自适应调整时。
  • 使用 rem
    • 当你需要在整个项目中保持一致的尺寸比例时。
    • 当你在进行响应式设计时,可以通过改变根元素的字体大小来统一调整所有使用 rem 的元素。
    • 当你希望避免多层嵌套带来的复杂计算问题时。

实际工作中的使用技巧

  • 浏览器默认字体大小:如果你希望你的设计更加健壮,可以考虑使用 JavaScript 来动态设置根元素的字体大小。

  • 选择合适的单位:根据布局的需求选择 emremem 适用于需要继承父元素尺寸的情况,而 rem 适用于需要全局一致性的场景。

  • 设置根元素字体大小:通过设置 <html> 元素的字体大小,大多数浏览器的默认字体大小是 16px,但用户可以自定义这个值。可以方便地调整整个页面的字体大小和其他尺寸。

  • 兼容性考虑:尽管现代浏览器广泛支持 emrem 单位,但在老版本浏览器中,仍需注意兼容性问题。

  • 响应式设计:结合媒体查询使用 emrem 单位,可以实现更加灵活的响应式布局。

  • 易用性:使用 emrem 单位可以提高页面的可访问性,特别是对于视力不佳的用户。

通过理解 emrem 的区别,你可以更好地选择合适的单位来构建灵活且易于维护的CSS布局。

三者的区别:

  • px 是固定的像素,一旦设置了就无法因为适应页面大小而改变。
  • em 和 rem 相对于 px 更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
  • em 是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而 rem 是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。

使用场景:

  • 对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用 px 即可 。
  • 对于需要适配各种移动设备,使用 rem,例如需要适配 iPhone 和 iPad 等分辨率差别比较挺大的设备。

rem 适配手机端代码 rem的适配方案

一、rem适配方案1、rem+媒体查询+less技术

1、设计搞常见的尺寸宽度

一般情况下,我们以两套大部分适应的屏幕,放弃极端屏对其优雅降级,牺牲一些效果,现在基本以750为准

2、动态设置 html 标签 font-size 大小

假设设计稿是750px

  • 假设我们把整个屏幕划分为15等分(划分标准不一可以是20等份也可以是10等份)
  • 每一份作为html字体大小,这里就是50px
  • 那么在320px设备的时候,字体大小为320/15 就是21.33px
  • 用我们页面元素的大小  除以不同的 html 字体大小会发现他们比例还是相同的
  • 比如我们以750 为标准设计稿
  • 一个100*100像素的页面元素在 750屏幕下,就是 100  /  50转换为rem 是 2rem * 2rem 比例是1比1
  • 320屏幕下,html字体大小就为 21.33 则2rem = 42.66px, 此时宽和高 都是42.66, 但是高和宽还是1比1
  • 但是已经能实现不同屏幕下,页面元素盒子等比例缩放的效果

3、元素大小取值方法

  • 最后的公式:页面元素的rem值 = 页面元素值(px) /  (屏幕宽度 /  划分的份数)
  • 屏幕的宽度 / 划分的份数就是 html font-size 的大小
  • 或者:页面元素的rem值 =  页面元素值 (px) /  html font-size 字体大小

4、总结出得一个媒体查询的公共文件 common.less

// 定义一个公共的common.less文件  先装nodejs node -v

// npm install -g less 查看下安装成功没 lessc -v

// vscode 插件可以直接将less文件转换为css文件  (Easy-LESS)

// 设置常见的屏幕尺寸, 修改里面的html文字大小

// 一定要写最上面 

html{

  font-size: 50px;

}

// 我是定义的划分是15等份

@no: 15;

// 320

@media screen and (min-width: 320px){

  html{

    font-size: 320px / @no;

  }

}

// 360

@media screen and (min-width: 360px){

  html{

    font-size: 360px / @no;

  }

}

// 375 iphone 678

@media screen and (min-width: 384px){

  html{

    font-size: 384px / @no;

  }

}

@media screen and (min-width: 400px){

  html{

    font-size: 400px / @no;

  }

}

@media screen and (min-width: 414px){

  html{

    font-size: 414px / @no;

  }

}

@media screen and (min-width: 424px){

  html{

    font-size: 424px / @no;

  }

}

@media screen and (min-width: 480px){

  html{

    font-size: 480px / @no;

  }

}

@media screen and (min-width: 540px){

  html{

    font-size: 540px / @no;

  }

}

@media screen and (min-width: 720px){

  html{

    font-size: 720px / @no;

  }

}

@media screen and (min-width: 750px){

  html{

    font-size: 750px / @no;

  }

}

二、rem适配方案2 简洁高效rem适配方案flexible.js

手机淘宝团队出的简洁高效移动端适配库 我们再也不需要在写不同屏幕的媒体查询,因为里面js做了处理 它的原理是把设备划分成10等份,但在不同设备下,比例还是一致的 我们要做的就是确定好我们当前设备的html 文字字体大小就可以了 比如当前设计稿是750px 那么只需要把html文字大小设置为75px (750px/10)就可以 里面页面元素rem值:页面元素的px值 / 75 剩余的,让flexible.js去计算

github地址:  https://github.com/amfe/lib-flexible

3. 两栏布局的实现

一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:

  • float+BFC
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>两栏布局</title>
        <style>
            /* 方法1  左元素固定宽度,向左浮动 右元素不设置宽度,会自动撑满,重叠问题可使用BFC解决 */
            /* float让元素脱离正常标准流控制,不再占有原来的位置,*/
            /* overflow: hidden是关键,也可改成其他能触发BFC均可解决 利用了BFC的特点:`BFC` 的区域不会与浮动元素发生重叠 */
			.left {
                width: 200px;
                height: 100px;
                background-color: red;
                float:left;
            }
            .right {
                height: 200px;
                background-color: blue;
                overflow: hidden;
            }

        </style>
    </head>
    <body >
		<div class="outer">
			<div class="left">左侧</div>
			<div class="right">右侧</div>
		</div>
    </body>
</html>

  • 利用浮动,将左边元素宽度设置为 200px,并且设置向左浮动。将右边元素的 margin-left 设置为 200px,宽度设置为 auto(默认为 auto,撑满整个父元素)。
.outer {
  height: 100px;
}
.left {
  float: left;
  width: 200px;
  background: tomato;
}
.right {
  margin-left: 200px;
  width: auto;
  background: gold;
}
  • 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置 overflow: hidden; 这样右边就触发了 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
.left{
     width: 100px;
     height: 200px;
     background: red;
     float: left;
 }
 .right{
     height: 300px;
     background: blue;
     overflow: hidden;
 }
  • 利用 flex 布局,将左边元素设置为固定宽度 200px,将右边的元素设置为 flex:1。
.outer {
  display: flex;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  flex: 1;
  background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素设置为 absolute 定位,并且宽度设置为 200px。将右边元素的 margin-left 的值设置为 200px。
.outer {
  position: relative;
  height: 100px;
}
.left {
  position: absolute;
  width: 200px;
  height: 100px;
  background: tomato;
}
.right {
  margin-left: 200px;
  background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为 200px,右边元素设置为绝对定位,左边定位为 200px,其余方向定位为 0。
.outer {
  position: relative;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 200px;
  background: gold;
}

4. 三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的 margin 的值。
<div class="outer">
  <div class="center">center</div>
  <div class="left"></div>
  <div class="right"></div>
</div>
<style>
  body {
    padding: 0;
    margin: 0;
  }
  .outer {
    position: relative;
    height: 100px;
  }

  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    background: tomato;
  }

  .right {
    position: absolute;
    top: 0;
    right: 0;
    width: 200px;
    height: 100px;
    background: gold;
  }

  .center {
    margin-left: 100px;
    margin-right: 200px;
    height: 100px;
    background: lightgreen;
  }
</style>
  • 利用 flex 布局,左右两栏设置固定大小,中间一栏设置为 flex:1。
.outer {
  display: flex;
  height: 100px;
}

.left {
  width: 100px;
  background: tomato;
}

.right {
  width: 100px;
  background: gold;
}

.center {
  flex: 1;
  background: lightgreen;
}
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的 margin 值,注意这种方式**,中间一栏必须放到最后:**
.outer {
  height: 100px;
}

.left {
  float: left;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: right;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  height: 100px;
  margin-left: 100px;
  margin-right: 200px;
  background: lightgreen;
}
  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
.outer {
    height: 100px;
    padding: 0 200px 0 200px;
  }

  .left,
  .center,
  .right {
    height: 100px;
  }

  .left {
    float: left;
    width: 200px;
    background-color: red;
    margin-left: -100%;
    position: relative;
    left: -200px;
  }

  .right {
    float: left;
    width: 200px;
    height: 100px;
    background: gold;
    margin-left: -200px;
    position: relative;
    left: 200px;
  }

  .center {
    float: left;
    background-color: blue;
    width: 100%;
  }
  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。(需要在中间的布局中插入一元素,这个元素里设置 margin,中间的父级和左右浮动都是 left ---float:left)
.outer {
  height: 100px;
}

.left {
  float: left;
  margin-left: -100%;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: left;
  margin-left: -200px;
  width: 200px;
  height: 100px;
  background: gold;
}

.wrapper {
  float: left;
  height: 100px;
  background: lightgreen;
  margin-left: 100px;
  margin-right: 200px;
}

.center {
  width: 100%;
  height: 100px;
}

5. 水平垂直居中的实现

  • 利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 translate 来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。
.parent {
    position: relative;
}

.child {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
  • 利用绝对定位,设置四个方向的值都为 0,并将 margin 设置为 auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:
.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
  • 利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 margin 负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况
.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -50px;     /* 自身 height 的一半 */
    margin-left: -50px;    /* 自身 width 的一半 */
}
  • 使用 flex 布局,通过 align-items:center 和 justify-content:center 设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:
.parent {
    display: flex;
    justify-content:center;
    align-items:center;
}

6. 如何根据设计稿进行移动端适配?

移动端适配主要有两个维度:

  • **适配不同像素密度,**针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;
  • **适配不同屏幕大小,**由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容。

为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位。

7. 对 Flex 布局的理解及其使用场景

Flex 是 FlexibleBox 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。行内元素也可以使用 Flex 布局。注意,设为 Flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿水平主轴排列。

以下 6 个属性设置在容器上

  • flex-direction 属性决定主轴的方向(即项目的排列方向)。
  • flex-wrap 属性定义,如果一条轴线排不下,如何换行。
  • flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap。
  • justify-content 属性定义了项目在主轴上的对齐方式。
  • align-items 属性定义项目在交叉轴上如何对齐。
  • align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

以下 6 个属性设置在项目上

  • order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为 0。
  • flex-grow 属性定义项目的放大比例,默认为 0,即如果存在剩余空间,也不放大。
  • flex-shrink 属性定义了项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小。
  • flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。
  • flex 属性是 flex-grow,flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。
  • align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。

简单来说:

flex 布局是 CSS3 新增的一种布局方式,可以通过将一个元素的 display 属性值设置为 flex 从而使它成为一个 flex 容器,它的所有子元素都会成为它的项目。一个容器默认有两条轴:一个是水平的主轴,一个是与主轴垂直的交叉轴。可以使用 flex-direction 来指定主轴的方向。可以使用 justify-content 来指定元素在主轴上的排列方式,使用 align-items 来指定元素在交叉轴上的排列方式。还可以使用 flex-wrap 来规定当一行排列不下时的换行方式。对于容器中的项目,可以使用 order 属性来指定项目的排列顺序,还可以使用 flex-grow 来指定当排列空间有剩余的时候,项目的放大比例,还可以使用 flex-shrink 来指定当排列空间不足时,项目的缩小比例。

8. flex:1 表示什么

flex 属性是 flex-grow,flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。flex:1 表示 flex: 1 1 0%:

  • 第一个参数表示: flex-grow 定义项目的放大比例,默认为 0,即如果存在剩余空间,也不放大;
  • 第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小;
  • 第三个参数表示: flex-basis 给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小。

9. 响应式设计的概念及基本原理

响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。

关于原理: 基本原理是通过媒体查询(@media)查询检测不同的设备屏幕尺寸做处理。

关于兼容: 页面头部必须有 mate 声明的viewport

<meta name="’viewport’" content="”width=device-width," initial-scale="1." maximum-scale="1,user-scalable=no”"/>

10. 实现“品” 字布局

品字布局就像下图这样:

img

(1)浮动实现

我们可以使用定位实现,对于上面的 1,使用 magin 属性让他水平居中;下面的两个使用浮动即可实现,其 HTML 结构如下:

<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>

CSS 代码如下:

div{
  width:100px;
  height:100px;
  font-size:40px;
  line-height:100px;
  color:#fff;
  text-align:center;
}

.div1{
  background:red;
  margin:0 auto;
}

.div2{
  background: green;
  float:left;
  margin-left: 50%;
}

.div3{
  background: blue;
  float:left;
  margin-left: -200px;
}

该方法是在在三个盒子的宽高都知道的情况下才能实现的。

(2)inline-block 实现

HTML 结构如下:

<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>

这里将 div 设置为了 inline-block,实际上和上面的 float 的作用是一眼的,就是让下面的两个块不换行。使用 CSS 样式如下:

div{
  width:100px;
  height:100px;
  font-size:40px;
  line-height:100px;
  color:#fff;
  text-align:center;
}

.div1{
  background:red;
  margin:0 auto;
}

.div2{
  background: green;
  display: inline-block;
  margin-left: 50%;
}

.div3{
  background: blue;
  display: inline-block;
  margin-left: -200px;
}

11. 实现九宫格布局

实现效果如下:

img

首先,定义好通用的 HTML 结构:

<div class="box">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
</div>

公共样式:

ul {
	padding: 0;
}

li {
	list-style: none;
    text-align: center;
	border-radius: 5px;
	background: skyblue;
}

(1)flex 实现

对于九宫格布局,我首先想到的就是 flex 布局,flex 布局实现九宫格很简单,需要设置一个 flex-wrap: wrap;使得盒子在该换行的时候进行换行。

由于我们给每个元素设置了下边距和右边距,所以最后同一列(3、6、9)的右边距和最后一行(7、8、9)的下边距撑大了 ul,所以这里使用类型选择器来消除他们的影响。最终的实现代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .flex-box {
        width: 500px;
        height: 500px;
        background-color: red;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-around;
        align-content: space-around;
      }
      .flex-item {
        width: 150px;
        height: 150px;
        box-sizing: border-box;
        border: 1px solid #ccc;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    </style>
  </head>
  <body>
    <div class="flex-box">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
      <div class="flex-item">3</div>
      <div class="flex-item">4</div>
      <div class="flex-item">5</div>
      <div class="flex-item">6</div>
      <div class="flex-item">7</div>
      <div class="flex-item">8</div>
      <div class="flex-item">9</div>
    </div>
  </body>
</html>

(2)grid 实现

grid 布局相对于 flex 布局来说,实现九宫格就更加容易了,只需要设置几个属性即可:

ul {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 30% 30% 30%;
  grid-template-rows: 30% 30% 30%;
  grid-gap: 5%;
}

其中 grid-template-columns 属性用来设置每一行中单个元素的宽度,grid-template-rows 属性用来设置每一列中单个元素的高度,grid-gap 属性用来设置盒子之间的间距。

其实 Grid 布局还是很有用,很方便的,近期会有一篇详解 grid 布局的文章,有想了解的小伙伴可以关注一波嗷~

(3)float 实现

这里首先需要给父元素的 div 设置一个宽度,宽度值为:**盒子宽 * 3 + 间距 * 2;**然后给每个盒子设置固定的宽高,为了让他换行,可以使用 float 来实现,由于子元素的浮动,形成了 BFC,所以父元素 ul 使用 overflow:hidden;来消除浮动带来的影响。最终的实现代码如下:

ul {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

li {
  float: left;
  width: 30%;
  height: 30%;
  margin-right: 5%;
  margin-bottom: 5%;
}

li:nth-of-type(3n){
  margin-right: 0;
}

li:nth-of-type(n+7){
  margin-bottom: 0;
}

(4)inline-block 实现

其实 inline-block 的作用和上面 float 的作用是一样的,都是用来让元素换行的,实现代码如下:

ul {
  width: 100%;
  height: 100%;
  letter-spacing: -10px;
}

li {
  width: 30%;
  height: 30%;
  display: inline-block;
  margin-right: 5%;
  margin-bottom: 5%;
}

li:nth-of-type(3n){
  margin-right: 0;
}

li:nth-of-type(n+7){
  margin-bottom: 0;
}

需要注意的是,设置为 inline-block 的元素之间可能会出现间隙,就可能出现下面这种情况:

img

这里使用了 letter-spacing 属性来消除这种影响,该属性可以用来增加或减少字符间的空白(字符间距)。使用之后就正常了,出现了预期的效果。也可以给 ul 设置 font-size: 0;来消除盒子之间的字符间距:

ul {
  font-size: 0;
}

(5)table 实现

HTML 结构:

<ul class="table">
  <li>
    <div>1</div>
    <div>2</div>
    <div>3</div>
  </li>
  <li>
    <div>4</div>
    <div>5</div>
    <div>6</div>
  </li>
  <li>
    <div>7</div>
    <div>8</div>
    <div>9</div>
  </li>
</ul>

table 布局也不算太难,首先给父元素设置为 table 布局,然后使用 border-spacing 设置单元格之间的间距,最后将 li 设置为表格行,将 div 设置为表格单元格,CSS 样式如下:

.table {
  width: 100%;
  height: 100%;
  display: table;
  border-spacing: 10px;
}

li {
  display: table-row;
}

div {
  width: 30%;
  height: 30%;
  display: table-cell;
  text-align: center;
  border-radius: 5px;
  background: skyblue;
}

12.flex 布局最后一行列表左对齐

在 CSS flex 布局中,justify-content 属性可以控制列表的水平对齐方式,例如 space-between 值可以实现两端对齐。

但是,如果最后一行的列表的个数不满,则就会出现最后一行没有完全垂直对齐的问题。

二、处理方法 我们可以使用空白标签进行填充占位

<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <i></i><i></i><i></i><i></i><i></i>
</div>
.container {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
}
.list {
    width: 100px;
    height:100px;
}
/* 和列表一样的宽度和margin值 */
.container > i {
    width: 100px;
}

由于<i>元素高度为 0,因此,并不会影响垂直方向上的布局呈现。

三、采用 grid 布局 Grid 布局天然有 gap 间隙,且天然格子对齐排布,因此,实现最后一行左对齐可以认为是天生的效果。

html

<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
</div>
.container {
    display: grid;
    justify-content: space-between;
    grid-template-columns: repeat(auto-fill, 100px);
}
.list {
    width: 100px;
    height:100px;
}

三、定位与浮动

1. 为什么需要清除浮动?清除浮动的方式

浮动的定义: 非 IE 浏览器下,容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器外面而影响布局。这种现象被称为浮动(溢出)。

浮动的工作原理:

  • 浮动元素脱离文档流,不占据空间(引起“高度塌陷”现象)
  • 浮动元素碰到包含它的边框或者其他浮动元素的边框停留

浮动元素可以左右移动,直到遇到另一个浮动元素或者遇到它外边缘的包含框。浮动框不属于文档流中的普通流,当元素浮动之后,不会影响块级元素的布局,只会影响内联元素布局。此时文档流中的普通流就会表现得该浮动框不存在一样的布局模式。当包含框的高度小于浮动框的时候,此时就会出现“高度塌陷”。

浮动元素引起的问题?

  • 父元素的高度无法被撑开,影响与父元素同级的元素
  • 与浮动元素同级的非浮动元素会跟随其后
  • 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构

清除浮动的方式如下:

  • 给父级 div 定义height属性
  • 最后一个浮动元素之后添加一个空的 div 标签,并添加clear:both样式
  • 包含浮动元素的父级标签添加overflow:hidden或者overflow:auto
  • 使用 :after 伪元素。由于 IE6-7 不支持 :after,使用 zoom:1 触发 hasLayout**
.clearfix:after{
    content: "\200B";
    display: table;
    height: 0;
    clear: both;
  }
  .clearfix{
    *zoom: 1;
  }

2. 使用 clear 属性清除浮动的原理?

使用 clear 属性清除浮动,其语法如下:

clear:none|left|right|both

如果单看字面意思,clear:left 是“清除左浮动”,clear:right 是“清除右浮动”,实际上,这种解释是有问题的,因为浮动一直还在,并没有清除。

官方对 clear 属性解释:“元素盒子的边不能和前面的浮动元素相邻”,对元素设置 clear 属性是为了避免浮动元素对该元素的影响,而不是清除掉浮动。

还需要注意 clear 属性指的是元素盒子的边不能和前面的浮动元素相邻,注意这里“前面的”3 个字,也就是 clear 属性对“后面的”浮动元素是不闻不问的。考虑到 float 属性要么是 left,要么是 right,不可能同时存在,同时由于 clear 属性对“后面的”浮动元素不闻不问,因此,当 clear:left 有效的时候,clear:right 必定无效,也就是此时 clear:left 等同于设置 clear:both;同样地,clear:right 如果有效也是等同于设置 clear:both。由此可见,clear:left 和 clear:right 这两个声明就没有任何使用的价值,至少在 CSS 世界中是如此,直接使用 clear:both 吧。

一般使用伪元素的方式清除浮动:

.clear::after{
  content:'';
  display: block;
  clear:both;
}

clear 属性只有块级元素才有效的,而::after 等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置 display 属性值的原因。

3. 对 BFC 的理解,如何创建 BFC

先来看两个相关的概念:

  • Box: Box 是 CSS 布局的对象和基本单位,⼀个⻚⾯是由很多个 Box 组成的,这个 Box 就是我们所说的盒模型。
  • Formatting context:块级上下⽂格式化,它是⻚⾯中的⼀块渲染区域,并且有⼀套渲染规则,它决定了其⼦元素将如何定位,以及和其他元素的关系和相互作⽤。

块级格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

通俗来讲:BFC 是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发 BFC 的条件,则 BFC 中的元素布局不受外部影响。

创建 BFC 的条件:

  • 根元素:body;
  • 元素设置浮动:float 除 none 以外的值;
  • 元素设置绝对定位:position (absolute、fixed);
  • display 值为:inline-block、table-cell、table-caption、flex 等;
  • overflow 值为:hidden、auto、scroll;

BFC 的特点:

  • 垂直方向上,自上而下排列,和文档流的排列方式一致。
  • 在 BFC 中上下相邻的两个容器的 margin 会重叠
  • 计算 BFC 的高度时,需要计算浮动元素的高度
  • BFC 区域不会与浮动的容器发生重叠
  • BFC 是独立的容器,容器内部元素不会影响外部元素
  • 每个元素的左 margin 值和容器的左 border 相接触

BFC 的作用:

  • 解决 margin 的重叠问题:由于 BFC 是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个 BFC,就解决了 margin 重叠的问题。
  • 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为 0。解决这个问题,只需要把父元素变成一个 BFC。常用的办法是给父元素设置overflow:hidden
  • 创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。
.left{
     width: 100px;
     height: 200px;
     background: red;
     float: left;
 }
 .right{
     height: 300px;
     background: blue;
     overflow: hidden;
 }

<div class="left"></div>
<div class="right"></div>

左侧设置float:left,右侧设置overflow: hidden。这样右边就触发了 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠,实现了自适应两栏布局。

4. 什么是 margin 重叠问题?如何解决?

问题描述:

两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向

计算原则:

折叠合并后外边距的计算原则如下:

  • 如果两者都是正数,那么就去最大者
  • 如果是一正一负,就会正值减去负值的绝对值
  • 两个都是负值时,用 0 减去两个中绝对值大的那个

解决办法:

对于折叠的情况,主要有两种:兄弟之间重叠父子之间重叠

(1)兄弟之间重叠

  • 底部元素变为行内盒子:display: inline-block
  • 底部元素设置浮动:float
  • 底部元素的 position 的值为absolute/fixed

(2)父子之间重叠

  • 父元素加入:overflow: hidden
  • 父元素添加透明边框:border:1px solid transparent
  • 子元素变为行内盒子:display: inline-block
  • 子元素加入浮动属性或定位

5. 元素的层叠顺序

层叠顺序,英文称作 stacking order,表示元素发生层叠时有着特定的垂直显示顺序。下面是盒模型的层叠规则:

img

对于上图,由上到下分别是:

(1)背景和边框:建立当前层叠上下文元素的背景和边框。

(2)负的 z-index:当前层叠上下文中,z-index 属性值为负的元素。

(3)块级盒:文档流内非行内级非定位后代元素。

(4)浮动盒:非定位浮动元素。

(5)行内盒:文档流内行内级非定位后代元素。

(6)z-index:0:层叠级数为 0 的定位元素。

(7)正 z-index:z-index 属性值为正的定位元素。

注意: 当定位元素 z-index:auto,生成盒在当前层叠上下文中的层级为 0,不会建立新的层叠上下文,除非是根元素。

6. position 的属性有哪些,区别是什么

position 有以下属性值:

属性值概述
absolute生成绝对定位的元素,相对于 static 定位以外的一个父元素进行定位。元素的位置通过 left、top、right、bottom 属性进行规定。
relative生成相对定位的元素,相对于其原来的位置进行定位。元素的位置通过 left、top、right、bottom 属性进行规定。
fixed生成绝对定位的元素,指定元素相对于屏幕视⼝(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变,⽐如回到顶部的按钮⼀般都是⽤此定位⽅式。
static默认值,没有定位,元素出现在正常的文档流中,会忽略 top, bottom, left, right 或者 z-index 声明,块级元素从上往下纵向排布,⾏级元素从左向右排列。
inherit规定从父元素继承 position 属性的值

前面三者的定位方式如下:

  • **relative:**元素的定位永远是相对于元素自身位置的,和其他元素没关系,也不会影响其他元素。

img

  • **fixed:**元素的定位是相对于 window (或者 iframe)边界的,和其他元素没有关系。但是它具有破坏性,会导致其他元素位置的变化。

img

  • **absolute:**元素的定位相对于前两者要复杂许多。如果为 absolute 设置了 top、left,浏览器会根据什么去确定它的纵向和横向的偏移量呢?答案是浏览器会递归查找该元素的所有父元素,如果找到一个设置了position:relative/absolute/fixed的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。如下两个图所示:

img

img

7. display、float、position 的关系

(1)首先判断 display 属性是否为 none,如果为 none,则 position 和 float 属性的值不影响元素最后的表现。

(2)然后判断 position 的值是否为 absolute 或者 fixed,如果是,则 float 属性失效,并且 display 的值应该被设置为 table 或者 block,具体转换需要看初始转换值。

(3)如果 position 的值不为 absolute 或者 fixed,则判断 float 属性的值是否为 none,如果不是,则 display 的值则按上面的规则转换。注意,如果 position 的值为 relative 并且 float 属性的值存在,则 relative 相对于浮动后的最终位置定位。

(4)如果 float 的值为 none,则判断元素是否为根元素,如果是根元素则 display 属性按照上面的规则转换,如果不是,则保持指定的 display 属性值不变。

总的来说,可以把它看作是一个类似优先级的机制,"position:absolute"和"position:fixed"优先级最高,有它存在的时候,浮动不起作用,'display'的值也需要调整;其次,元素的'float'特性的值不是"none"的时候或者它是根元素的时候,调整'display'的值;最后,非根元素,并且非浮动元素,并且非绝对定位的元素,'display'特性值同设置值。

8. absolute 与 fixed 共同点与不同点

共同点:

  • 改变行内元素的呈现方式,将 display 置为 inline-block
  • 使元素脱离普通文档流,不再占据文档物理空间
  • 覆盖非定位文档元素

不同点:

  • absolute 与 fixed 的根元素不同,absolute 的根元素可以设置,fixed 根元素是浏览器。
  • 在有滚动条的页面中,absolute 会跟着父元素进行移动,fixed 固定在页面的具体位置。

9. 对 sticky 定位的理解

sticky 英文字面意思是粘贴,所以可以把它称之为粘性定位。语法:position: sticky; 基于用户的滚动位置来定位。

粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。

四、场景应用

1. 实现一个三角形

CSS 绘制三角形主要用到的是 border 属性,也就是边框。

平时在给盒子设置边框时,往往都设置很窄,就可能误以为边框是由矩形组成的。实际上,border 属性是由三角形组成的,下面看一个例子:

div {
    width: 0;
    height: 0;
    border: 100px solid;
    border-color: orange blue red green;
}

将元素的长宽都设置为 0,显示出来的效果是这样的:

img

所以可以根据 border 这个特性来绘制三角形:

(1)三角 1

div {
    width: 0;
    height: 0;
    border-top: 50px solid red;
    border-right: 50px solid transparent;
    border-left: 50px solid transparent;
}

img

(2)三角 2

div {
    width: 0;
    height: 0;
    border-bottom: 50px solid red;
    border-right: 50px solid transparent;
    border-left: 50px solid transparent;
}

img

(3)三角 3

div {
    width: 0;
    height: 0;
    border-left: 50px solid red;
    border-top: 50px solid transparent;
    border-bottom: 50px solid transparent;
}

img

(4)三角 4

div {
    width: 0;
    height: 0;
    border-right: 50px solid red;
    border-top: 50px solid transparent;
    border-bottom: 50px solid transparent;
}

img

(5)三角 5

div {
    width: 0;
    height: 0;
    border-top: 100px solid red;
    border-right: 100px solid transparent;
}

img

还有很多,就不一一实现了,总体的原则就是通过上下左右边框来控制三角形的方向,用边框的宽度比来控制三角形的角度。

2. 实现一个扇形

用 CSS 实现扇形的思路和三角形基本一致,就是多了一个圆角的样式,实现一个 90° 的扇形:

div{
    border: 100px solid transparent;
    width: 0;
    height: 0;
    border-radius: 100px;
    border-top-color: red;
}

img

3. 实现一个圆和半圆

(1)实现圆:

div {
  background-color: red;
  height: 100px;
  width: 100px;
  border-radius: 50%;
}

**注意:**在使用 border-radius 时,使用 50%和 100%都可以得到一个圆,那这两个值到底有什么区别呢:border-radius 的值是百分比的话,就相当于盒子的宽度和高度的百分比。如一个 50px 150px 的方形,如果 border-radius 设置为 100%,则等价于:

border-radius: 50px/150px; 1

而 border-radius 又是由 border-top-left-radius、border-top-right-radius、border-bottom-left-radius、border-bottom-right-radius 组成,所有上面 border-radius:100%又等价于:

border-top-left-radius: 100%;
border-top-right-radius: 100%;
border-bottom-left-radius: 100%;
border-bottom-right-radius: 100%;

border-top-left-radius: 50px 150px;
border-top-right-radius: 50px 150px;
border-bottom-left-radius: 50px 150px;
border-bottom-right-radius: 50px 150px;

为什么 border-radius 设置成 100%和 50%都能画成圆呢?因为,在 W3C 中对重合曲线做了规定:如果两个相邻的半径和超过了对应的盒子的边的长度,那么浏览器要重新计算以保证它们不重合。也就是说,如果相邻圆角的半径都设置成大于 50%,那么浏览器会根据图形的实际情况做一些计算。因此,为了避免不必要的计算,建议使用 border-radius: 50%。

(2)实现半圆:

div {
  background-color: red;
  width: 100px;
  height: 50px;
  border-radius: 0px 0px 100px 100px;
}

4. 实现一个宽高自适应的正方形

  • 利用 vw 来实现:
.square {
  width: 10%;
  height: 10vw;
  background: tomato;
}

  • 利用元素的 margin/padding 百分比是相对父元素 width 的性质来实现:
.square {
  width: 20%;
  height: 0;
  padding-top: 20%;
  background: orange;
}

  • 利用子元素的 margin-top 的值来实现:
.square {
  width: 30%;
  overflow: hidden;
  background: yellow;
}
.square::after {
  content: '';
  display: block;
  margin-top: 100%;
}

4. 画一个梯形

<div class="trapezoid"></div>

(1)实现一个直角梯形:

.trapezoid {
    height: 0;
    width: 100px;
    border-bottom: 100px solid red;
    border-right: 40px solid transparent;
}

效果:

img

(2)实现一个等腰梯形

.trapezoid {
  height:0;
  width:100px;
  border-width:0 40px 100px 40px;
  border-style:none solid solid;
  border-color:transparent transparent red;
}

效果:

img

5. 画一条 0.5px 的线

  • 采用 transform: scale()的方式,该方法用来定义元素的 2D 缩放转换:
transform: scale(0.5,0.5);

  • 采用 meta viewport 的方式
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>

这样就能缩放到原来的 0.5 倍,如果是 1px 那么就会变成 0.5px。viewport 只针对于移动端,只在移动端上才能看到效果

6. 设置小于 12px 的字体

在谷歌下 css 设置字体大小为 12px 及以下时,显示都是一样大小,都是默认 12px。

解决办法:

  • 使用 Webkit 的内核的-webkit-text-size-adjust 的私有 CSS 属性来解决,只要加了-webkit-text-size-adjust:none;字体大小就不受限制了。但是 chrome 更新到 27 版本之后就不可以用了。所以高版本 chrome 谷歌浏览器已经不再支持-webkit-text-size-adjust 样式,所以要使用时候慎用。
  • 使用 css3 的 transform 缩放属性-webkit-transform:scale(0.5); 注意-webkit-transform:scale(0.75);收缩的是整个元素的大小,这时候,如果是内联元素,必须要将内联元素转换成块元素,可以使用 display:block/inline-block/...;
  • 使用图片:如果是内容固定不变情况下,使用将小于 12px 文字内容切出做图片,这样不影响兼容也不影响美观。

7. 如何解决 1px 问题?

1px 问题指的是:在一些 Retina屏幕 的机型上,移动端页面的 1px 会变得很粗,呈现出不止 1px 的效果。原因很简单——CSS 中的 1px 并不能和移动设备上的 1px 划等号。它们之间的比例关系有一个专门的属性来描述:

window.devicePixelRatio = 设备的物理像素 / CSS像素。

打开 Chrome 浏览器,启动移动端调试模式,在控制台去输出这个 devicePixelRatio 的值。这里选中 iPhone6/7/8 这系列的机型,输出的结果就是 2:

img

这就意味着设置的 1px CSS 像素,在这个设备上实际会用 2 个物理像素单元来进行渲染,所以实际看到的一定会比 1px 粗一些。

**解决****1px 问题的三种思路:**

思路一:直接写 0.5px

如果之前 1px 的样式这样写:

border:1px solid #333

可以先在 JS 中拿到 window.devicePixelRatio 的值,然后把这个值通过 JSX 或者模板语法给到 CSS 的 data 里,达到这样的效果(这里用 JSX 语法做示范):

<div id="container" data-device={{window.devicePixelRatio}}></div>

然后就可以在 CSS 中用属性选择器来命中 devicePixelRatio 为某一值的情况,比如说这里尝试命中 devicePixelRatio 为 2 的情况:

#container[data-device="2"] {
  border:0.5px solid #333
}

直接把 1px 改成 1/devicePixelRatio 后的值,这是目前为止最简单的一种方法。这种方法的缺陷在于兼容性不行,IOS 系统需要 8 及以上的版本,安卓系统则直接不兼容。

思路二:伪元素先放大后缩小

这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。

思路是先放大、后缩小:**在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后、整个伸展开铺在目标元素上,然后把它的**宽和高都设置为目标元素的两倍,border 值设为 1px。**接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一**,间接地实现了 0.5px 的效果。

代码如下:

#container[data-device="2"] {
    position: relative;
}
#container[data-device="2"]::after{
      position:absolute;
      top: 0;
      left: 0;
      width: 200%;
      height: 200%;
      content:"";
      transform: scale(0.5);
      transform-origin: left top;
      box-sizing: border-box;
      border: 1px solid #333;
    }
}

思路三:viewport 缩放来解决

这个思路就是对 meta 标签里几个关键属性下手:

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

这里针对像素比为 2 的页面,把整个页面缩放为了原来的 1/2 大小。这样,本来占用 2 个物理像素的 1px 样式,现在占用的就是标准的一个物理像素。根据像素比的不同,这个缩放比例可以被计算为不同的值,用 js 代码实现如下:

const scale = 1 / window.devicePixelRatio;
// 这里 metaEl 指的是 meta 标签对应的 Dom
metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);

这样解决了,但这样做的副作用也很大,整个页面被缩放了。这时 1px 已经被处理成物理像素大小,这样的大小在手机上显示边框很合适。但是,一些原本不需要被缩小的内容,比如文字、图片等,也被无差别缩小掉了。

8、实现一个三饼

    <style>
      .box {
        width: 200px;
        height: 300px;
        padding: 20px;
        display: flex;
        flex-direction: row;
        justify-content: space-between; /*设置两端对齐*/
        border: 2px solid #ccc;
        border-radius: 10px;
      }
      .item {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        background-color: red;
      }
      .item:nth-child(2) {
        align-self: center; /*垂直方向居中*/
        background-color: green;
      }
      .item:nth-child(3) {
        align-self: flex-end; /*垂直方尾对齐*/
        background-color: blue;
      }
    </style>

    <div class="box">
      <div class="item"></div>
      <div class="item"></div>
      <div class="item"></div>
    </div>

9. 实现左右固定中间自适应的布局

实现左右固定、中间自适应的布局在Web设计中是一个常见的需求。这种布局通常适用于需要侧边栏和主要内容区域的情况,其中侧边栏宽度固定,而主要内容区域根据浏览器窗口大小自动调整其宽度。以下是几种实现这种布局的方法:

1. 使用浮动(Float)

这是一种传统的CSS方法,通过给左右两侧设置固定宽度并使用float属性,使中间部分自适应。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fixed Sides, Flexible Center</title>
<style>
  .container {
    overflow: hidden; /* 清除浮动 */
  }
  .left, .right {
    width: 200px;
    float: left; /* 左侧浮动 */
  }
  .right {
    float: right; /* 右侧浮动 */
  }
  .center {
    margin: 0 200px; /* 中间部分的外边距等于左右侧边栏的宽度 */
  }
</style>
</head>
<body>
<div class="container">
  <div class="left">Left Sidebar</div>
  <div class="center">Main Content</div>
  <div class="right">Right Sidebar</div>
</div>
</body>
</html>

2. 使用Flexbox

Flexbox提供了一种更现代且灵活的方式来处理布局问题。它可以让容器中的子元素按照弹性方式排列。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fixed Sides, Flexible Center</title>
<style>
  .container {
    display: flex;
  }
  .left, .right {
    width: 200px;
  }
  .center {
    flex-grow: 1; /* 自动填充剩余空间 */
  }
</style>
</head>
<body>
<div class="container">
  <div class="left">Left Sidebar</div>
  <div class="center">Main Content</div>
  <div class="right">Right Sidebar</div>
</div>
</body>
</html>

3. 使用Grid布局

CSS Grid是一种强大的二维布局系统,可以很容易地创建复杂的布局结构。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fixed Sides, Flexible Center</title>
<style>
  .container {
    display: grid;
    grid-template-columns: 200px auto 200px; /* 左右固定宽度,中间自适应 */
  }
</style>
</head>
<body>
<div class="container">
  <div class="left">Left Sidebar</div>
  <div class="center">Main Content</div>
  <div class="right">Right Sidebar</div>
</div>
</body>
</html>

4. 使用绝对定位(Absolute Positioning)

这种方法通过将左右两侧定位到绝对位置,并让中间部分占据剩余的空间。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fixed Sides, Flexible Center</title>
<style>
  .container {
    position: relative;
  }
  .left, .right {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 200px;
  }
  .left {
    left: 0;
  }
  .right {
    right: 0;
  }
  .center {
    margin: 0 200px; /* 中间部分的外边距等于左右侧边栏的宽度 */
  }
</style>
</head>
<body>
<div class="container">
  <div class="left">Left Sidebar</div>
  <div class="center">Main Content</div>
  <div class="right">Right Sidebar</div>
</div>
</body>
</html>

每种方法都有其优缺点,选择哪种方法取决于你的具体需求以及你希望支持的浏览器版本。对于现代网站开发,推荐使用Flexbox或Grid布局,因为它们提供了更多的灵活性和更好的跨浏览器兼容性。

前端常见的布局方式

  • 流式布局(Fluid Layout页面宽度按屏幕分辨率调整,随浏览器窗口大小变化,适合内容灵活的页面。流式布局是一种基于比例的布局方式,可以根据浏览器窗口的大小自动调整页面元素的宽度。通过设定百分比的宽度,使页面元素能够随着窗口的缩放而自动调整。这种布局方式适合于不同尺寸的设备,可以提供更好的响应性。

  • 固定布局(Fixed Layout固定布局是指页面元素的宽度和高度都是固定的像素值。这种布局方式适用于那些不需要自适应的页面,比如后台管理系统或者固定尺寸的广告页面。固定布局能够提供精确的控制,但在不同尺寸的设备上可能会出现显示问题。

  • 栅格布局(Grid Layout栅格布局是一种基于网格的布局方式,通过网格划分页面,适合需要精确排版的页面。将页面分为多个行和列,通过设定网格单位的宽度和高度来布局页面元素。栅格布局适用于大型网站和应用程序的布局,能够提供更好的结构和组织。

  • 弹性布局(Flexbox Layout简便、完整地实现各种页面布局,适合响应式设计。弹性布局是一种基于弹性盒子的布局方式,可以自动调整页面元素的大小和位置。通过设定弹性容器和弹性子项的属性,可以实现不同尺寸设备的适配。弹性布局适用于复杂的页面布局,但在老旧浏览器上可能不兼容。

  • 响应式布局(Responsive Layout响应式布局是一种综合运用以上布局方式的布局方式。通过使用媒体查询和其他技术手段,可以根据不同设备的屏幕尺寸和分辨率,为用户提供最佳的浏览体验。响应式布局能够适应不同的设备,提高用户获得信息的便捷性。

  • 浮动布局

    浮动布局是调用浮动属性来使得元素向左或者向右移动从而共享一行,直到碰到包含框或者另一个浮动框。浮动元素是脱离文档流的,不占据页面空间,但不脱离文本流,且浮动会将行内元素和行内块元素转化为块元素。

    特点:

    1. 脱离标准普通流的控制(浮) 移动到指定位置(动), (俗称脱标)。
    2. 浮动的盒子不再保留原先的位置,会一行内显示并且元素顶部对齐。
    3. 浮动的元素会具有行内块元素的特性。

    优点:

    1. 排版友好,例如图文排版或者首字母下沉排版等。
    2. 兼容性好。

    缺点: 需要调整网站布局对代码改动很大,页面的宽度不够会影响布局。浮动是脱标的,那么就无法撑起父元素造成塌陷。

  • 卡片式布局‌将内容以卡片形式展示,适合信息块独立的页面。

  • 单页应用布局‌所有页面内容在一个页面中,通过内部链接和滚动条切换页面。

  • 静态布局‌为页面设定固定宽高,适合门户网站和企业官网。

  • 自适应布局‌根据屏幕大小调整布局,适合移动设备。

  • 定位布局‌通过定位实现页面布局,适合需要精确控制位置的页面。定位布局是给元素设置 position 属性从而控制元素显示在不规则的位置,偏向于单个元素定位操作。

这些布局方式可以根据具体需求和场景进行选择和组合使用,以达到最佳的用户体验效果。

参考网站:https://www.cnblogs.com/wangtiantian/p/18043153

FLEX布局

Flexbox(弹性盒子布局)是CSS3引入的一种布局模式,它为复杂和响应式的网页设计提供了更强大的能力。Flexbox使得容器中的子元素能够灵活地扩展、收缩,并在不同屏幕尺寸下自动调整布局,而无需使用浮动或定位。

基本概念

  • 容器(Container):应用了 display: flexdisplay: inline-flex 的元素。
  • 项目(Item):容器内的直接子元素。
  • 主轴(Main Axis):默认情况下是从左到右的水平轴,可以通过 flex-direction 属性改变方向。
  • 交叉轴(Cross Axis):与主轴垂直的轴,如果主轴是水平的,那么交叉轴就是垂直的。

容器属性

  • display:设置为 flexinline-flex 以启用Flexbox。
  • flex-direction:定义主轴的方向(row, row-reverse, column, column-reverse)。
  • flex-wrap:定义项目是否换行(nowrap, wrap, wrap-reverse)。
  • justify-content:定义项目在主轴上的对齐方式(flex-start, flex-end, center, space-between, space-around, space-evenly)。
  • align-items:定义项目在交叉轴上的对齐方式(stretch, flex-start, flex-end, center, baseline)。
  • align-content:定义多行项目的对齐方式(仅在有多个flex行时有效)。

项目属性

  • order:定义项目的排列顺序。
  • flex-grow:定义项目的放大比例,默认为0,即不放大。
  • flex-shrink:定义项目的缩小比例,默认为1,即空间不足时会缩小。
  • flex-basis:定义项目在分配多余空间之前的基础大小。
  • flexflex-grow, flex-shrink, 和 flex-basis 的简写。
  • align-self:允许单个项目有与其他项目不一样的对齐方式,可以覆盖 align-items 属性。

示例

以下是一个简单的例子,展示了如何使用Flexbox来创建一个左右固定宽度、中间自适应宽度的布局:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flexbox Layout</title>
<style>
  .container {
    display: flex;
    height: 100vh; /* 使容器高度占满整个视口 */
  }
  .left, .right {
    width: 200px;
    background-color: #f4f4f4; /* 背景颜色用于区分 */
  }
  .left {
    background-color: lightblue; /* 左侧背景颜色 */
  }
  .right {
    background-color: lightgreen; /* 右侧背景颜色 */
  }
  .center {
    flex-grow: 1; /* 中间部分填充剩余空间 */
    background-color: lightcoral; /* 中间背景颜色 */
  }
</style>
</head>
<body>
<div class="container">
  <div class="left">Left Sidebar</div>
  <div class="center">Main Content</div>
  <div class="right">Right Sidebar</div>
</div>
</body>
</html>

在这个例子中:

  • .container 是一个Flex容器,设置了 display: flex
  • .left.right 是固定宽度的侧边栏。
  • .center 使用了 flex-grow: 1,这使得它会占据所有剩余的空间,从而实现了中间部分的自适应布局。

更多应用场景

  • 居中对齐:通过 justify-content: centeralign-items: center 可以轻松实现水平和垂直居中。
  • 等分列:通过 flex: 1 可以让所有的项目等分父容器的空间。
  • 响应式布局:结合媒体查询,可以根据不同的屏幕尺寸调整布局。

Flexbox非常适合构建现代Web页面,尤其是那些需要良好响应性和灵活性的设计。通过合理地使用这些属性,你可以创造出既美观又实用的布局。

水平垂直居中

当然,让我们更准确地讨论如何在 CSS 中实现元素的水平垂直居中。以下是几种精确的方法,每种方法都适用于不同的场景和布局需求:

1. 使用 Flexbox

Flexbox 是一种非常灵活且强大的布局模型,特别适用于一维布局(水平或垂直)以及二维布局(同时水平和垂直)。

html复制代码

<div class="container">  
  <div class="centered">我是居中的</div>  
</div>
css复制代码

.container {  
  display: flex;  
  justify-content: center; /* 水平居中 */  
  align-items: center;     /* 垂直居中 */  
  height: 100vh;           /* 使容器高度等于视口高度 */  
}  
  
.centered {  
  /* 可以根据需要添加其他样式,如宽度、高度、背景色等 */  
}

这种方法适用于任何类型的子元素(块级、内联块、内联等),并且不需要知道子元素的尺寸。

2. 使用 CSS Grid

CSS Grid 布局是另一种强大的二维布局系统,可以轻松实现水平和垂直居中。

html复制代码

<div class="container">  
  <div class="centered">我是居中的</div>  
</div>
css复制代码

.container {  
  display: grid;  
  place-items: center; /* 同时实现水平和垂直居中 */  
  height: 100vh;       /* 使容器高度等于视口高度 */  
}  
  
.centered {  
  /* 可以根据需要添加其他样式 */  
}

与 Flexbox 类似,Grid 布局也不需要知道子元素的尺寸,并且适用于任何类型的子元素。

3. 使用绝对定位和 CSS 变换

这种方法适用于已知子元素尺寸的情况,并且需要将父元素设置为相对定位。

html复制代码

<div class="container">  
  <div class="centered">我是居中的</div>  
</div>
css复制代码

.container {  
  position: relative;  
  height: 100vh; /* 使容器高度等于视口高度 */  
}  
  
.centered {  
  position: absolute;  
  top: 50%;  
  left: 50%;  
  transform: translate(-50%, -50%); /* 使用变换将元素移动到中心 */  
  /* 可以根据需要添加其他样式,如宽度、高度、背景色等 */  
}

4. 使用内联块和文本对齐(不推荐,但了解有用)

这种方法较为过时,但在某些特定情况下仍然可能有用。它依赖于将父元素设置为表格显示,并将子元素设置为表格单元格显示。

html复制代码

<div class="container">  
  <div class="centered">我是居中的</div>  
</div>
css复制代码

.container {  
  display: table;  
  width: 100%;  
  height: 100vh; /* 使容器高度等于视口高度 */  
  text-align: center; /* 水平居中(仅对内联或内联块元素有效) */  
  vertical-align: middle; /* 尝试垂直居中,但这对块级元素无效 */  
  /* 注意:vertical-align 在这里对块级元素 .centered 无效 */  
}  
  
.centered {  
  display: inline-block; /* 使其成为内联块元素以应用 text-align */  
  vertical-align: middle; /* 这实际上不会起作用,因为父元素不是行内元素 */  
  /* 需要额外的技巧来垂直居中,如使用伪元素或额外的 HTML 结构 */  
  /* 但通常不推荐这种方法,因为它不够直观且容易出错 */  
}  
  
/* 替代方案(不推荐的方法中的额外技巧): */  
/* 使用伪元素来创建垂直居中的效果 */  
.container::before {  
  content: '';  
  display: inline-block;  
  height: 100%;  
  vertical-align: middle;  
  margin-right: -0.25em; /* 微调以消除可能的空白间隙 */  
}

注意:上面的内联块和文本对齐方法实际上并不能直接实现垂直居中,因为 vertical-align 对块级元素无效。这里只是为了完整性而提及,并展示了为什么这种方法不推荐使用。如果你真的想使用这种方法,你需要额外的技巧,比如使用伪元素,但这会使代码变得复杂且难以维护。

总结

对于大多数现代布局需求,Flexbox 和 CSS Grid 是首选方法,因为它们既强大又易于使用。如果你需要兼容旧版浏览器,并且可以接受一些额外的 HTML 结构或 CSS 技巧,那么绝对定位和变换也是一个可行的选择。内联块和文本对齐方法通常不推荐使用,因为它们不够直观且容易出错。

外边距折叠

在CSS中,两个或多个毗邻的普通流中的盒子(可能是父子元素,也可能是兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加。

什么时候会发生外边距折叠?

存在两种情况:一是父子外边距叠加;二是兄弟外边距叠加。

  • 普通流中的块级元素的margin-bottom永远和它相邻的下一个块级元素的margin-top叠加,除非相邻的兄弟元素clear
  • 普通流中的块级元素(没有border-top、没有padding-top)的margin-top和它的第一个普通流中的子元素(没有clear)发生margin-top叠加
  • 普通流中的块级元素(height为auto、min-height为0、没有border-bottom、没有padding-bottom)和它的最后一个普通流中的子元素(没有自身发生margin叠加或clear)发生margin-bottom叠加-
  • 如果一个元素的min-height为0、没有border、没有padding、高度为0或者auto、不包含子元素,那么它自身的外边距会发生叠加。

外边距折叠后的大小

  • 两个相同大小的正数:取某个外边距的值。即30px与30px发生折叠,折叠后的值为30px。

  • 两个不同大小的正数:取较大的外边距的值。即30px与20px发生折叠,折叠后的值为30px。

  • 一正一负:取正数与负数的和。即30px与-20px发生折叠,折叠后的值为10px。

  • 相同大小的负数:同相同大小正数。-30px与-30px折叠,折叠后为-30px。

  • 不同大小负数: 取绝对值较大的负数。-30px与-20px折叠,折叠后为-30px

如何避免外边距折叠

  • 浮动元素不会与任何元素发生叠加,也包括它的子元素
  • 创建了BFC的元素不会和它的子元素发生外边距叠加
  • 绝对定位元素和其他任何元素之间不发生外边距叠加,也包括它的子元素
  • inline-block元素和其他任何元素之间不发生外边距叠加,也包括它的子元素

参考网站:https://www.cnblogs.com/cuijinlin/p/13645959.html#_label0

less 与 sass区别

Less 和 Sass 都是CSS预处理器,它们扩展了CSS的功能,提供了变量、嵌套规则、混合(mixins)、函数等特性,使得样式表的编写更加模块化和易于维护。尽管两者有很多相似之处,但它们在语法、功能和一些实现细节上有所不同。

1. 语法

  • Sass:

    • 提供两种语法:SCSS (Sassy CSS) 和缩进语法(.sass 文件)。
    • SCSS 与标准 CSS 语法非常相似,使用大括号 {} 和分号 ;
    • 缩进语法不使用大括号和分号,而是通过缩进来表示代码块。
    • 示例:
      // SCSS
      .container {
        width: 100%;
        .header {
          color: red;
        }
      }
      
      // 缩进语法
      .container
        width: 100%
        .header
          color: red
      
  • Less:

    • 只有一种语法,类似于标准 CSS,使用大括号 {} 和分号 ;
    • 示例:
      .container {
        width: 100%;
        .header {
          color: red;
        }
      }
      

2. 变量

  • Sass:

    • 使用 $ 符号定义变量。
    • 示例:$primary-color: #333;
  • Less:

    • 使用 @ 符号定义变量。
    • 示例:@primary-color: #333;

3. 混合(Mixins)

  • Sass:

    • 使用 @mixin 定义混合,使用 @include 调用。
    • 示例:
      @mixin border-radius($radius) {
        -webkit-border-radius: $radius;
           -moz-border-radius: $radius;
            -ms-border-radius: $radius;
                border-radius: $radius;
      }
      
      .box { @include border-radius(10px); }
      
  • Less:

    • 使用 .mixin-name()#mixin-name() 定义混合,调用时直接使用类名或ID名。
    • 示例:
      .border-radius(@radius) {
        -webkit-border-radius: @radius;
           -moz-border-radius: @radius;
            -ms-border-radius: @radius;
                border-radius: @radius;
      }
      
      .box { .border-radius(10px); }
      

4. 继承

  • Sass:

    • 使用 @extend 实现继承。
    • 示例:
      %message-shared {
        border: 1px solid #ccc;
        padding: 10px;
        color: #333;
      }
      
      .message {
        @extend %message-shared;
      }
      
  • Less:

    • 使用 &:extend(.class) 实现继承。
    • 示例:
      .message-shared {
        border: 1px solid #ccc;
        padding: 10px;
        color: #333;
      }
      
      .message {
        &:extend(.message-shared);
      }
      

5. 控制结构

  • Sass:

    • 支持 @if, @for, @each, @while 等控制结构。
    • 示例:
      @for $i from 1 through 3 {
        .item-#{$i} { width: 2em * $i; }
      }
      
  • Less:

    • 支持 @if, @when, @for, @while 等控制结构。
    • 示例:
      @for $i from 1 through 3 {
        .item-@{i} { width: 2em * @i; }
      }
      

6. 函数

  • Sass:

    • 提供丰富的内置函数,并允许用户自定义函数。
    • 示例:
      @function calculate-width($n) {
        @return $n * 2em;
      }
      
      .element { width: calculate-width(5); }
      
  • Less:

    • 也提供内置函数,并允许用户自定义函数。
    • 示例:
      .calculate-width(@n) {
        width: @n * 2em;
      }
      
      .element { .calculate-width(5); }
      

7. 社区和支持

  • Sass:

    • 由Ruby社区支持,拥有庞大的用户基础和活跃的生态系统。
    • 更多的第三方库和工具支持。
  • Less:

    • 由JavaScript社区支持,使用广泛,尤其是在Node.js环境中。
    • 也有许多插件和工具可用。

8. 性能

  • Sass:

    • 由于基于Ruby,编译速度可能较慢,特别是在大型项目中。
    • LibSass 是一个更快的C++实现,可以显著提高编译速度。
  • Less:

    • 基于JavaScript,通常编译速度较快,特别是在现代JavaScript引擎上运行时。

总结

选择 Less 还是 Sass 往往取决于个人偏好、团队习惯以及项目的具体需求。如果你喜欢更接近原生CSS的语法,并且希望有较好的性能表现,可能会倾向于使用 Less。而如果你需要更多的高级功能和强大的社区支持,Sass 可能是一个更好的选择。无论选择哪种,这两种预处理器都能极大地提升你的CSS开发体验。

css优化方式

  1. 精简代码
    • 移除无用的CSS代码:检查CSS文件,移除那些从未被使用或者已经失效的样式规则。
    • 合并重复的代码块:如果有多个地方使用了相同的样式,可以将其合并为一个规则。
    • 使用简写属性和值:例如,使用margin: 10px;代替margin-top: 10px; margin-right: 10px; margin-bottom: 10px; margin-left: 10px;
  2. 压缩CSS
    • 使用在线工具或构建工具(如Webpack、Gulp等)对CSS进行压缩,删除不必要的空格、换行和注释。
  3. 避免使用@import
    • 使用<link>标签直接链接到CSS文件,而不是使用@import。因为@import会阻塞页面的渲染,导致页面加载变慢。
  4. 选择高效的选择器
    • 使用ID选择器(如#myId)和类选择器(如.myClass)而不是标签选择器(如div)或属性选择器(如[type="text"])。
    • 避免使用过于复杂的选择器,如div#myId.myClass,这样的选择器会增加渲染时间。
  5. 避免使用过多的层级
    • 尽量减少CSS规则的嵌套层级。例如,避免写div.parent div.child { ... },而直接写.child { ... }
  6. 利用CSS继承
    • 利用CSS的继承机制,避免重复定义相同的样式。例如,如果一个元素的字体和颜色与其父元素相同,那么无需再次定义。
  7. 抽取公共样式
    • 对于那些在多个地方重复使用的样式,可以定义为一个公共类,然后在需要的地方应用这个类。
  8. 使用CSS预处理器
    • 使用Sass、Less等CSS预处理器,它们提供了变量、嵌套、混合等功能,可以帮助我们更好地组织和管理CSS代码。
  9. 优化图片资源
    • 对于CSS中使用的图片,使用工具进行压缩,以减小文件大小。
    • 对于一些简单的图形,可以考虑使用SVG代替PNG或JPEG,因为SVG文件通常更小且可缩放。
  10. 使用CSS3特性
    • 利用CSS3提供的特性,如圆角(border-radius)、阴影(box-shadow)、渐变(linear-gradient)等,可以减少对图片的依赖,从而减小文件大小和提高性能。

记住,虽然优化可以提高性能,但过度优化可能会使代码难以阅读和维护。因此,在优化过程中,需要找到一个平衡点,确保代码既高效又易于维护。

固定宽度多出的文本内容变成省略号

在CSS中,如果你希望当文本内容超出固定宽度的容器时显示省略号(...),你可以使用以下CSS属性来实现这一效果。这种技术通常用于确保文本不会溢出其容器,同时给用户一个提示,表示还有更多的内容。

单行文本省略号

对于单行文本,你可以使用 text-overflow: ellipsis 属性结合其他几个CSS属性来达到效果:

.ellipsis {
  white-space: nowrap;          /* 防止文本换行 */
  overflow: hidden;             /* 隐藏溢出的内容 */
  text-overflow: ellipsis;      /* 显示省略号 */
  width: 200px;                 /* 设置固定宽度 */
}

多行文本省略号

对于多行文本,CSS3提供了一个新的属性 -webkit-line-clamp,它可以用来限制显示的行数,并且在最后一行添加省略号。这个属性需要与 display: -webkit-box-webkit-box-orient: vertical 一起使用。

.multi-line-ellipsis {
  display: -webkit-box;         /* 使用Flexbox布局 */
  -webkit-box-orient: vertical; /* 垂直排列子元素 */
  -webkit-line-clamp: 3;        /* 限制显示3行 */
  overflow: hidden;             /* 隐藏溢出的内容 */
  text-overflow: ellipsis;      /* 显示省略号 */
  width: 200px;                 /* 设置固定宽度 */
}

注意:-webkit-line-clamp 是一个非标准的CSS属性,但它被广泛支持于现代浏览器(如Chrome, Safari, 新版Edge和Firefox)。对于不支持此属性的浏览器,可以考虑使用JavaScript或jQuery插件来实现类似的效果。

HTML示例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text Ellipsis</title>
<style>
  .container {
    margin: 20px;
  }
  .ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 200px;
    border: 1px solid #ccc;
    padding: 10px;
  }
  .multi-line-ellipsis {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 200px;
    border: 1px solid #ccc;
    padding: 10px;
  }
</style>
</head>
<body>
<div class="container">
  <div class="ellipsis">
    这是一个很长的文本,它超出了容器的宽度,应该以省略号结束。
  </div>
  <div class="multi-line-ellipsis">
    这是一个非常长的段落,它可能包含很多行文字。为了演示多行省略号的效果,我们在这里放置了大量的文本。当文本超过指定的行数时,将会显示省略号。
  </div>
</div>
</body>
</html>

在这个例子中,.ellipsis 类用于单行文本的省略号处理,而 .multi-line-ellipsis 类用于多行文本的省略号处理。通过设置 width 属性,你可以控制容器的具体宽度。

参考网站:https://blog.csdn.net/weixin_51081257/article/details/121304822

修改elementUI组件中的样式

Element UI 是一个基于 Vue 2 的桌面端组件库,提供了丰富的组件和良好的文档支持。如果你需要修改 Element UI 组件中的样式,有几种方法可以实现:

1. 使用 CSS 类覆盖

最直接的方法是通过添加自定义的 CSS 类来覆盖 Element UI 组件的默认样式。这种方法适用于简单的样式调整。

<template>
  <el-button class="custom-button">按钮</el-button>
</template>

<style scoped>
.custom-button {
  background-color: #409EFF;
  color: white;
  border: none;
}
</style>

2. 使用深度选择器

在 Vue 单文件组件中,scoped 样式默认只作用于当前组件。为了覆盖子组件(如 Element UI 组件)的样式,你可以使用深度选择器 >>> 或者 /deep/(对于一些预处理器)。

使用 >>> 深度选择器 (Sass, Less)

<template>
  <el-button>按钮</el-button>
</template>

<style lang="scss" scoped>
/deep/ .el-button {
  background-color: #409EFF;
  color: white;
  border: none;
}
</style>

使用 /deep/ 深度选择器 (Less, Stylus)

<template>
  <el-button>按钮</el-button>
</template>

<style lang="less" scoped>
/deep/ .el-button {
  background-color: #409EFF;
  color: white;
  border: none;
}
</style>

3. 全局样式

如果需要对所有实例进行全局样式的修改,可以在全局样式文件中添加样式规则。

/* 在全局样式文件中,例如 src/assets/styles/global.css */
.el-button {
  background-color: #409EFF;
  color: white;
  border: none;
}

然后在你的主入口文件(如 main.jsmain.ts)中引入这个全局样式文件:

import Vue from 'vue';
import App from './App.vue';
import './assets/styles/global.css'; // 引入全局样式

new Vue({
  render: h => h(App),
}).$mount('#app');

4. 自定义主题

Element UI 提供了主题定制功能,允许你通过变量来自定义整个UI的主题。你可以使用官方提供的在线主题编辑工具或本地配置来生成自定义主题。

使用在线主题编辑工具

  • 访问 Element UI 主题编辑器open in new window
  • 调整颜色和其他样式变量。
  • 导出并下载生成的主题文件。
  • 将生成的主题文件替换项目中的 theme/index.css 文件,并确保在项目中正确引用它。

本地配置

  • 安装依赖:

    npm install element-theme -D
    npm install element-theme-chalk -D
    
  • 创建主题配置文件 element-variables.scss 并修改变量:

    $--color-primary: #409EFF;
    // 更多变量...
    
  • 编译主题:

    et -c ./path/to/element-variables.scss
    
  • 编译后会生成新的 CSS 文件,将其引入到项目中。

5. 修改源码

如果上述方法都不能满足需求,你可以考虑直接修改 Element UI 的源码。不过这种方法不推荐,因为这会使后续升级变得困难,并且容易导致代码混乱。

总结

大多数情况下,使用 CSS 类覆盖、深度选择器或全局样式就足以满足大部分的样式修改需求。如果需要大规模的主题定制,建议使用 Element UI 提供的主题定制功能。这样不仅更加灵活,还能保持项目的整洁性和可维护性。

如何实现响应式布局

实现响应式布局是现代Web设计中的一个重要方面,它确保网站在不同设备和屏幕尺寸上都能提供良好的用户体验。响应式设计的主要目标是让网页能够自动适应各种屏幕大小,从桌面显示器到手机和平板电脑。以下是几种实现响应式布局的方法:

1. 使用媒体查询(Media Queries)

媒体查询是CSS3的一个功能,允许你根据设备的特性(如视口宽度、高度等)应用不同的样式。

示例

/* 默认样式 */
body {
  font-size: 16px;
}

.container {
  width: 80%;
  margin: 0 auto;
}

/* 当屏幕宽度小于或等于600px时 */
@media (max-width: 600px) {
  body {
    font-size: 14px;
  }

  .container {
    width: 90%;
  }
}

/* 当屏幕宽度大于600px且小于或等于900px时 */
@media (min-width: 601px) and (max-width: 900px) {
  .container {
    width: 70%;
  }
}

/* 当屏幕宽度大于900px时 */
@media (min-width: 901px) {
  .container {
    width: 60%;
  }
}

2. 使用灵活的网格系统

使用CSS Grid或Flexbox可以轻松创建灵活的布局,这些布局会根据可用空间自动调整。

CSS Grid 示例

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.item {
  background-color: #f0f0f0;
  padding: 20px;
}

Flexbox 示例

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.item {
  flex: 1 1 200px; /* 基于内容大小扩展,最小200px */
  background-color: #f0f0f0;
  padding: 20px;
}

3. 使用相对单位

使用相对单位(如%, em, rem, vw, vh)可以使元素的大小相对于其父容器或视口尺寸进行调整,从而提高布局的灵活性。

示例

.container {
  width: 80%; /* 相对于父元素 */
  padding: 20px;
}

.text {
  font-size: 1rem; /* 相对于根元素的字体大小 */
}

.image {
  max-width: 100%; /* 图片最大宽度不超过其容器 */
  height: auto;
}

4. 流动布局(Fluid Layouts)

流动布局通过百分比来定义元素的宽度,使它们能够根据父容器的宽度进行调整。

示例

.header, .footer {
  width: 100%;
  background-color: #333;
  color: white;
  padding: 20px;
}

.content, .sidebar {
  box-sizing: border-box;
  padding: 20px;
}

.content {
  width: 75%;
  float: left;
}

.sidebar {
  width: 25%;
  float: right;
}

5. 移动优先设计

移动优先是一种设计理念,先为小屏幕设备设计,然后逐步增加样式以适应更大的屏幕。这通常通过媒体查询来实现。

示例

/* 移动端默认样式 */
.container {
  width: 90%;
  margin: 0 auto;
}

/* 平板及以上的样式 */
@media (min-width: 600px) {
  .container {
    width: 80%;
  }
}

/* 桌面及以上的样式 */
@media (min-width: 1024px) {
  .container {
    width: 70%;
  }
}

6. 使用框架

许多前端框架(如Bootstrap, Foundation, Tailwind CSS)提供了现成的响应式组件和工具类,可以帮助你快速构建响应式布局。

Bootstrap 示例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-12 col-md-8">主要内容</div>
      <div class="col-12 col-md-4">侧边栏</div>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

总结

实现响应式布局的关键在于灵活地使用CSS技术,如媒体查询、灵活的网格系统、相对单位以及移动优先的设计理念。选择合适的技术组合取决于你的具体需求和项目规模。使用前端框架可以加速开发过程,但自定义CSS可以提供更精细的控制。

Last Updated:
Contributors: 乙浒