前端CSS常见面试题(二)
前言
- 接上文,继续补充前端CSS常见面试题。
页面布局单位及设计(重点)
CSS布局单位
常用的布局单位包括像素(px
),百分比(%
),em
,rem
,vw/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:相对于视窗的尺寸
px、em、rem的区别
px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
em和rem相对于px更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
em是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。
flex布局
容器
首先,实现 flex 布局需要先指定一个容器,任何一个容器都可以被指定为 flex 布局,这样容器内部的元素就可以使用 flex 来进行布局。
.container { display: flex | inline-flex; //可以有两种取值 }
需要注意的是:当时设置 flex 布局之后,子元素的 float、clear、vertical-align 的属性将会失效。
有下面六种属性可以设置在容器上,它们分别是:
1、flex-direction
2、flex-wrap
3、flex-flow
4、justify-content
5、align-items
6、align-content
- flex-direction: 决定主轴的方向(即项目的排列方向)
.container { flex-direction: row | row-reverse | column | column-reverse; }
默认值:row,主轴为水平方向,起点在左端。
row-reverse:主轴为水平方向,起点在右端
column:主轴为垂直方向,起点在上沿
column-reverse:主轴为垂直方向,起点在下沿
- flex-wrap: 决定容器内项目是否可换行
默认情况下,项目都排在主轴线上,使用 flex-wrap 可实现项目的换行。
wrap:项目主轴总尺寸超出容器时换行,第一行在上方
wrap-reverse:换行,第一行在下方
- flex-flow: flex-direction 和 flex-wrap 的简写形式
.container { flex-flow: <flex-direction> || <flex-wrap>; }
默认值为: row nowrap(这里是分开的两个属性哦)
- justify-content:定义了项目在主轴的对齐方式。
.container { justify-content: flex-start | flex-end | center | space-between | space-around; }
建立在主轴为水平方向时测试,即 flex-direction: row
默认值: flex-start 左对齐:
flex-end:右对齐
center:居中
space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙。
space-around:每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍。
- align-items: 定义了项目在交叉轴上的对齐方式
.container { align-items: flex-start | flex-end | center | baseline | stretch; }
建立在主轴为水平方向时测试,即 flex-direction: row
默认值为 stretch 即如果项目未设置高度或者设为 auto,将占满整个容器的高度。
假设容器高度设置为 100px,而项目都没有设置高度的情况下,则项目的高度也为 100px。
flex-start:交叉轴的起点对齐
假设容器高度设置为 100px,而项目分别为 20px, 40px, 60px, 80px, 100px, 则如上图显示。
flex-end:交叉轴的终点对齐
center:交叉轴的中点对齐
baseline: 项目的第一行文字的基线对齐
- align-content: 定义了多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用
.container { align-content: flex-start | flex-end | center | space-between | space-around | stretch; }
子容器
上述讲的是一个容器可以设置的属性,下面讲的是容器内的子容器
- flex-grow 属性
- flex-grow 属性定义子元素或者子容器的放大比例,默认为 0,即如果存在剩余空间,也不放大。
flex-shrink
属性:
- flex-shrink 属性定义了项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小。
flex-basis 属性
- flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。
flex简写
flex 简写属性在下面有三个值的定义 默认值为 0 1 auto;
- flex-grow :定义项目的放大比例,默认为 0
- flex-shrink :定义项目的缩小比例,默认为 1
- flex-basis :定义项目在分配多余的空间之前,项目占据的主轴空间 默认为 auto(item 本来大小)
flex:1
完整形式:flex:1 = flex: 1 1 0%;
flex:1 在父元素尺寸不足的时候,会优先最小化内容尺寸。
使用场景:当我们希望元素可以充分的利用剩余的空间,同时不会很多的占用其他同级元素的空间的时候使用。
flex:auto
完整形式:flex:auto = flex: 1 1 auto;
- flex:auto 在父元素尺寸不足的时候,会优先最大化内容尺寸。
- 使用场景:当我们希望元素充分的使用剩余的空间,各自元素按照各自内容进行分配的时候使用。
flex:0
完整形式:flex:0 = flex: 0 1 0%;
- flex:0 :通常表现为
内容最小化宽度
- 使用场景:当希望元素 item 占用最小化的内容宽度的时候
flex:none
完整形式:flex:none = flex:0 0 auto;
- flex:none;表示元素的大小由内容决定,但是 flex-grow,flex-shrink 都是 0,元素没有弹性,通常表现为
内容最大化宽度
- 使用场景:元素的宽度就是内容的宽度,并且内容永远不会换行
常见布局
两栏布局
一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:
- 利用浮动,将左边元素宽度设置为 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; }
等宽布局
<body> <div id="parent"> <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div> <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div> <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div> <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div> </div> </body>
- 使用 float 实现
#parent { margin-left: -20px; /*使整体内容看起来居中,抵消 padding-left 的影响*/ } .column{ padding-left: 20px; /*盒子的边距*/ width: 25%; float: left; box-sizing: border-box; border: 1px solid #000; background-clip: content-box; /*背景色从内容开始绘制,方便观察*/ height: 500px; } .column:nth-child(odd){ background-color: #f00; } .column:nth-child(even){ background-color: #0f0; }
- 使用 flex 实现
#parent { margin-left: -15px; /*使内容看起来居中*/ height: 500px; display: flex; } .column{ flex: 1; /*一起平分#parent*/ margin-left: 15px; /*设置间距*/ } .column:nth-child(odd){ background-color: #f00; } .column:nth-child(even){ background-color: #0f0; }
九宫格布局
- 使用 flex 实现
<body> <div id="parent"> <div class="row"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> </div> <div class="row"> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> </div> <div class="row"> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> </div> </div> </body>
#parent { width: 1200px; height: 500px; margin: 0 auto; display: flex; flex-direction: column; } .row { display: flex; flex: 1; } .item { flex: 1; border: 1px solid #000; }
全屏布局
- 使用绝对定位实现
<body> <div id="parent"> <div id="top">top</div> <div id="left">left</div> <div id="right">right</div> <div id="bottom">bottom</div> </div> </body>
html, body, #parent {height: 100%;overflow: hidden;} #parent > div { border: 1px solid #000; } #top { position: absolute; top: 0; left: 0; right: 0; height: 100px; } #left { position: absolute; top: 100px; /*值大于等于#top 的高度*/ left: 0; bottom: 50px; /*值大于等于#bottom 的高度*/ width: 200px; } #right { position: absolute; overflow: auto; left: 200px; /*值大于等于#left 的宽度*/ right: 0; top: 100px; /*值大于等于#top 的高度*/ bottom: 50px; /*值大于等于#bottom 的高度*/ } #bottom { position: absolute; left: 0; right: 0; bottom: 0; height: 50px; }
- 使用 flex 实现
<body> <div id="parent"> <div id="top">top</div> <div id="middle"> <div id="left">left</div> <div id="right">right</div> </div> <div id="bottom">bottom</div> </div> </body>
*{ margin: 0; padding: 0; } html,body,#parent{ height:100%; } #parent { display: flex; flex-direction: column; } #top { height: 100px; } #bottom { height: 50px; } #middle { flex: 1; display: flex; } #left { width: 200px; } #right { flex: 1; overflow: auto; }
圣杯布局
- 圣杯布局是常见的三栏式布局。两边顶宽,中间自适应的三栏布局。
<div class="container"> <div class="middle">测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</div> <div class="left">left</div> <div class="right">right</div> </div>
.container{ padding: 0 200px; } .middle{ width: 100%; background: paleturquoise; height: 200px; float: left; } .left{ background: palevioletred; width: 200px; height: 200px; float: left; font-size: 40px; color: #fff; margin-left: -100% ; position: relative; left: -200px; } .right{ width: 200px; height: 200px; background: purple; font-size: 40px; float: left; color: #fff; margin-left:-200px; position: relative; right: -200px; }
双飞翼布局
<div class="container"> <div class="middle-container"> <div class="middle">测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</div> </div> <div class="left">left</div> <div class="right">right</div> </div>
.middle-container{ width: 100%; background: paleturquoise; height: 200px; float: left; } .middle{ margin-left: 200px; margin-right: 200px; } .left{ background: palevioletred; width: 200px; height: 200px; float: left; font-size: 40px; color: #fff; margin-left:-100%; } .right{ width: 200px; height: 200px; background: purple; font-size: 40px; float: left; color: #fff; margin-left:-200px; }
水平垂直居中(重点)
定宽高
- 绝对定位和负 magin 值
<template> <div id="app"> <div class="box"> <div class="children-box"></div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; position: relative; } .children-box { position: absolute; width: 100px; height: 100px; background: yellow; left: 50%; top: 50%; margin-left: -50px; margin-top: -50px; } </style>
- 绝对定位 + transform
<template> <div id="app"> <div class="box"> <div class="children-box"></div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; position: relative; } .children-box { position: absolute; width: 100px; height: 100px; background: yellow; left: 50%; top: 50%; transform: translate(-50%, -50%); } </style>
- 绝对定位 + left/right/bottom/top + margin
<template> <div id="app"> <div class="box"> <div class="children-box"></div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; position: relative; } .children-box { position: absolute; display: inline; top: 0; left: 0; right: 0; bottom: 0px; background: yellow; margin: auto; height: 100px; width: 100px; } </style>
- flex 布局
<template> <div id="app"> <div class="box"> <div class="children-box"></div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; display: flex; justify-content: center; align-items: center; } .children-box { background: yellow; height: 100px; width: 100px; } </style>
不定宽高
- 绝对定位 + transform
<template> <div id="app"> <div class="box"> <div class="children-box">111111</div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; position: relative; } .children-box { position: absolute; background: yellow; left: 50%; top: 50%; transform: translate(-50%, -50%); } </style>
- table-cell
<template> <div id="app"> <div class="box"> <div class="children-box">111111</div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; display: table-cell; text-align: center; vertical-align: middle; } .children-box { background: yellow; display: inline-block; } </style>
- flex 布局
<template> <div id="app"> <div class="box"> <div class="children-box">11111111</div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; display: flex; justify-content: center; align-items: center; } .children-box { background: yellow; } </style>
- flex 变异布局
<template> <div id="app"> <div class="box"> <div class="children-box">11111111</div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; display: flex; } .children-box { background: yellow; margin: auto; } </style>
- grid + flex 布局
<template> <div id="app"> <div class="box"> <div class="children-box">11111111</div> </div> </div> </template> <style type="text/css"> .box { width: 200px; height: 200px; border: 1px solid red; display: grid; } .children-box { background: yellow; align-self: center; justify-self: center; } </style>
内联元素居中布局
水平居中
行内元素可设置:text-align: center;
flex 布局设置父元素:display: flex; justify-content: center;
垂直居中
- 单行文本父元素确认高度:height === line-height
- 多行文本父元素确认高度:disaply: table-cell; vertical-align: middle;
块级元素居中布局
水平居中
- 定宽: margin: 0 auto;
- 不定宽: 参考上诉例子中不定宽高例子。
垂直居中
- position: absolute 设置 left、top、margin-left、margin-to(定高);
- position: fixed 设置 margin: auto(定高);
- display: table-cell;
- transform: translate(x, y);
- flex(不定高,不定宽);
- grid(不定高,不定宽),兼容性相对比较差;
定位(重点)
清除浮动
浮动定义
- 非IE浏览器下,容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器外面而影响布局。这种现象被称为浮动(溢出)。
浮动元素引起的问题
- 父元素的高度无法被撑开,影响与父元素同级的元素
- 与浮动元素同级的非浮动元素会跟随其后
- 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构
清除浮动的方式
- 给父级div定义
height
属性 - 最后一个浮动元素之后添加一个空的div标签,并添加
clear:both
样式 - 包含浮动元素的父级标签添加
overflow:hidden
或者overflow:auto
- 使用 :after 伪元素。
.clearfix:after{ content: "\200B"; display: table; height: 0; clear: both; } .clearfix{ *zoom: 1; }
BFC
块级格式化上下文,是一个独立的渲染区域,并且有一定的布局规则。
- BFC 区域不会与 float box 重叠
- BFC 是页面上的一个独立容器,子元素不会影响到外面
- 计算 BFC 的高度时,浮动元素也会参与计算
用于清除浮动,防止 margin 重叠等
哪些元素会生成 BFC:
- 根元素
- float 不为 none 的元素
- position 为 fixed 和 absolute 的元素
- display 为 inline-block、table-cell、table-caption,flex,inline-flex 的元素
- overflow 不为 visible 的元素
position的属性
- 这个相信大家都比较熟悉,就简单整理一下概念就好
属性值 | 概述 |
---|---|
absolute | 生成绝对定位的元素,相对于static定位以外的一个父元素进行定位。元素的位置通过left、top、right、bottom属性进行规定。 |
relative | 生成相对定位的元素,相对于其原来的位置进行定位。元素的位置通过left、top、right、bottom属性进行规定。 |
fixed | 生成绝对定位的元素,指定元素相对于屏幕视⼝(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变,⽐如回到顶部的按钮⼀般都是⽤此定位⽅式。 |
static | 默认值,没有定位,元素出现在正常的文档流中,会忽略 top, bottom, left, right 或者 z-index 声明,块级元素从上往下纵向排布,⾏级元素从左向右排列。 |
inherit | 规定从父元素继承position属性的值 |
position:sticky
用法
- position:sticky 被称为粘性定位元素(stickily positioned element)是计算后位置属性为 sticky 的元素。
- 简单的理解就是:在目标区域以内,它的行为就像 position:relative;在滑动过程中,某个元素距离其父元素的距离达到 sticky 粘性定位的要求时(比如 top:100px);position:sticky 这时的效果相当于 fixed 定位,固定到适当位置。
- 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于 viewport 来计算元素的偏移量。
使用条件
- 父元素不能 overflow:hidden 或者 overflow:auto 属性。
- 必须指定 top、bottom、left、right4 个值之一,否则只会处于相对定位
- 父元素的高度不能低于 sticky 元素的高度
- sticky 元素仅在其父元素内生效
offset/scroll/client 各类属性
- clientHeight:表示的是可视区域的高度,不包含 border 和滚动条
- offsetHeight:表示可视区域的高度,包含了 border 和滚动条
- scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。
- clientTop:表示边框 border 的厚度,在未指定的情况下一般为 0
- scrollTop:滚动后被隐藏的高度,获取对象相对于由 offsetParent 属性指定的父坐标(css 定位的元素或 body 元素)距离顶端的高度
clientX clientY
- 鼠标相对于浏览器窗口可视区域的 X,Y 坐标
pageX pageY
- 类似于 clientX,clientY,但它们使用的是文档坐标而非窗口坐标。具体来说,pageY = clientY + 页面滚动高度。
offsetX offsetY
- 鼠标相对于事件源元素(srcElement)的 X,Y 坐标。
absolute与fixed共同点与不同点
共同点:
- 改变行内元素的呈现方式,将display置为inline-block
- 使元素脱离普通文档流,不再占据文档物理空间
- 覆盖非定位文档元素
不同点:
- abuselute与fixed的根元素不同,abuselute的根元素可以设置,fixed根元素是浏览器。
- 在有滚动条的页面中,absolute会跟着父元素进行移动,fixed固定在页面的具***置。
分割线
- 以上就是整理后的前端CSS常见面试题,继续努力吧大家!