本文汇总多种方法,具体场景具体分析,注意使用的对象的分类:
- 文本、行内元素
- 块级元素
- 自适应内容的块级元素
基础方法
行内元素水平居中
text-align:center;//父元素属性
行内元素垂直居中
height:100px;//父元素属性
line-height:100px;//父元素属性行高==高度即可
大小确定的块级元素
margin:auto;//自身
传统布局模式
使用position的absolute实现居中
- 确定包含块 使用该方法时候,一定要对父元素进行定位,因为absolute是相对与static外的第一个父元素
补充:本质上absolute相对的是层叠上下文,所以CSS 3 transform属性不为none的也可以作为绝对定位的包含块
- 目标元素绝对定位
- left、top移动50%
- 上一步百分比移动是相对于(0,0)点的,所以需要移动自身长度的一半来居中
- 大小确定者,采用margin-left:一半宽度的负值;margin-top:一半高度的负值;
- 长度不确定
margin-lefttransform变形属性
#father{
width:100px;
height:100px;
background-color: aqua;
/* 父元素必须定位,即必须对position初始化,否则为默认值static */
position: fixed;
left:auto;
}
#son{
width:50px;
height:50px;
background-color:palevioletred;
position: absolute;
left:50%;
top:50%;
/* 百分比移动是相对于(0,0)点的,所以需要移动自身长度的一半来居中 */
margin-left:-25px;
margin-top:-25px;
}
自适应的块级元素想要用这个方法怎么办?
transform:translateX(-50%);// 注意CSS世界中没有几个属性的百分比是相对自己计算的
transform:translateY(-50%);
transform属性
- 该属性允许我们对元素进行旋转、缩放、移动或倾斜
- 内联元素不支持所有变换特性,无法应用transform
- 与clip-path出现在同一选择器中时,无论书写前后,先clip-path后transform
clip-path使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏
- 类似opacity不为1的元素,如果元素的transform不为none,就会创建一个新的层叠上下文
两张图片重叠时候,后DOM遮住前DOM,可以通过给前DOM设置transform:scale(1)调整
- 如果父元素使用了transform变换,子元素的fixed固定效果就会失效,表现类似absolute绝对定位,所以推荐外层元素负责定位,内层元素负责动画
fixed 相对于浏览器窗口进行定位
视口居中-视口单位+transform
vw 是与视口宽度相关的,1vw 表示视口宽度的 1%
- 1vmin=min(1vw, 1vh);
- 1vmax=max(1vw, 1vh);
#father{
width:100px;
height:100px;
background-color: aqua;
margin:50vh auto 50vw auto;
transform:translateY(-50%);
transform: translateX(-50%);
}
#son{
width:50px;
height:50px;
background-color:palevioletred;
margin:50vh auto 50vw auto;
transform:translateY(-50%);
transform: translateX(-50%);
}
缩放浏览器,元素保持视口居中
flex布局
传统布局基于盒状模型,依赖 display 属性 + position属性 + float属性。09年,W3C提出Flex布局 css单词通用含义
- justify水平方向
- align垂直方向
- items全体元素
- content整体布局
- self元素自身的样式,大部分是子元素
利用弹性盒子写一个菜单栏
首先一个简单的例子
/*外部容器设置为弹性*/
.site-nav {
display: flex;
padding: .5em;
background-color: #5f4b44;
list-style-type: none;
border-radius: .2em;
}
.site-nav > li {
margin-top: 0;
}
.site-nav > li > a {
display: block;
padding: .5em 1em;
background-color: #cc6b5a;
color: white;
text-decoration: none;
}
/*所有块的左部外边距*/
.site-nav > li + li {
margin-left: 1.5em;
}
/*设置最后一块的左部外边距为auto来让他填满容器,实现靠右的效果*/
.site-nav > .nav-right {
margin-left: auto;
}
- display:flex,该元素成为弹性容器,他的子元素成为弹性子元素
- flex容器存在方向不同的两条轴,主轴和交叉轴
- 项目主轴大小:子元素占据主轴方向上的长度。
- 子元素的float、clear、vertical-align失效。
属性
容器属性
flex-flow属性:flex-direction + flex-wrap
默认值为row、nowrap
在垂直的弹性盒子里,flex的收缩属性不会起作用
flex-direction主轴的方向即项目的排列方向
flex-direction:row;//默认控制子元素从左到右
column、row-reverse、column-reverse
flex-wrap默认项目都排列在轴线上,如果超出一行,该属性定义如何换行
nowrap不换行
wrap换行,下一行在下方
wrap-reverse换行,下一行在上方
启用之后,flex-shrink无效,元素不再收缩,直接折行
对齐:justify-content、align-content、align-items
justify-content 水平间距也可以理解为主轴上对齐方式
align-content属性值同justify-content,定义多根交叉轴线的对齐方式,即多行的间距
align-item属性定义flex子项在flex容器的当前行的侧轴(纵轴)方向上的对齐方式
子元素提供了align-self属性来覆盖align-item属性
常用来实现居中
子元素属性
- 子元素的float、clear、vertical-align失效
- 控制副轴上的属性align-items、align-content的初始值是stretch
- 弹性子元素像块级元素一样填充可用宽度,但是弹性子元素不一定填满其弹性容器的宽度
- 弹性子元素高度相等,高度由他们的内容决定。(换一个主轴方向就是等宽列)
- 将弹性子元素的margin设置为auto后,就可以实现子元素相对弹性容器居中。
order属性
定义项目排列顺序:值越小越前,默认值为0
flex属性
flex属性是简写属性
flex-grow
非负整数,子元素的盒模型占据之后的容器宽度可能会有留白
留白会将增长因子视作权重来分给子元素
0代表不增长
flex-shrink
子元素的盒模型占据之后的容器宽度可能不足
0代表不缩水
flex-basis
元素大小的基准值,作用于宽度还是高度取决于flex-direction
px、em、百分比
缩略特殊值:
flex:initial 默认值
flex:0 1 auto
flex: 0 等同于
flex: 0 1 0% 文字会显示为一柱擎天
flex: 1 等同于文字会显示为一柱擎天
flex: none 等同于
flex: 0 0 auto
flex:auto 等同于
flex:1 1 auto
grid布局
和弹性盒子类似,网格布局也是作用于两级DOM结构。
- display:grid,该元素成为一个网格容器,它的子元素成为网格元素。
- 网格语法有一个限制,所有网格元素必须是网格容器的直接子节点
定义网格轨道
- 新增属性定义网格轨道
- fr每一列的分数单位,权重
- 函数repeat
grid-template-rows: 1fr 1fr;
//等同于
grid-template-rows:repeat(2,1fr );
grid-template-columns: 2fr 1fr 1fr 3fr;
//等同于
grid-template-columns: 2fr repeat(2,1fr ) 3fr;
实现代码
<!doctype html>
<head>
<style>
:root {
box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: inherit;
}
.grid {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: 1fr 1fr;
grid-gap: 0.5em;
}
.grid > * {
background-color: darkgray;
color: white;
padding: 2em;
border-radius: 0.5em;
}
</style>
</head>
<body>
<div class="grid">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
<div class="e">e</div>
<div class="f">f</div>
</div>
</body>
隐式网格
隐式网格:上面显式定义了一个网格,在实际DOM中如果元素多于网格数会自动扩充网格
为隐式网络设置一个默认大小值
grid-auto-rows: 1fr;
grid-auto-colums: 1fr;
指定元素所占位置
grid-column: 起始网格线 / 终止网格线、或者span 网格数
.a{
grid-column: 1 / 3;
}
页面变化为
命名网格线
.container {
display: grid;
grid-template-columns: [left-start] 2fr
[left-end right-start] 1fr
[right-end];
grid-template-rows: repeat(4, [row] auto);
grid-gap: 1.5em;
max-width: 1080px;
margin: 0 auto;
}
header,
nav {
grid-column: left-start / right-end;
grid-row: span 1;
}
.main {
grid-column: left;
grid-row: row 3 / span 2;
}
.sidebar-top {
grid-column: right;
grid-row: 3 / 4;
}
命名网格区域
- 网格区域必须组成一个矩形
- . 作为名称 代表空出一个网格
.container {
display: grid;
grid-template-areas: "title title"
"nav ."
"main aside1"
"main aside2";
grid-template-columns: 2fr 1fr;
grid-template-rows: repeat(4, auto);
grid-gap: 1.5em;
max-width: 1080px;
margin: 0 auto;
}
特性查询
CSS查看浏览器支持特性与否 回退样式在特性查询之外
@supports (display: grid) {
.portfolio {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 1fr;
grid-gap: 1em;
grid-auto-flow: dense;
}
}
//抑或是
@supports not(display: grid){}
@supports (display: grid) or (display: table){}
@supports (display: grid) and (display: table){}
设置不同的大小
给部分元素占多个网格区域
.portfolio .featured {
grid-row: span 3;
grid-column: span 3;
}
前
后
所示变化发生在默认 grid-auto-flow:row;
例子
flex实现网页布局
<!doctype html>
<head>
<style>
:root {
box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: inherit;
}
body {
background-color: #709b90;
font-family: Helvetica, Arial, sans-serif;
}
body * + * {
margin-top: 1.5em;
}
.container {
max-width: 1080px;
margin: 0 auto;
}
.site-nav {
display: flex;
padding: .5em;
background-color: #5f4b44;
list-style-type: none;
border-radius: .2em;
}
.site-nav > li {
margin-top: 0;
}
.site-nav > li > a {
display: block;
padding: .5em 1em;
background-color: #cc6b5a;
color: white;
text-decoration: none;
}
.site-nav > li + li {
margin-left: 1.5em;
}
.site-nav > .nav-right {
margin-left: auto;
}
.tile {
padding: 1.5em;
background-color: #fff;
}
.flex {
display: flex;
}
.flex > * + * {
margin-top: 0;
margin-left: 1.5em;
}
.column-main {
flex: 2;
}
.column-sidebar {
flex: 1;
display: flex;
flex-direction: column;
}
.column-sidebar > .tile {
flex: 1;
}
.login-form h3 {
margin: 0;
font-size: .9em;
font-weight: bold;
text-align: right;
text-transform: uppercase;
}
.login-form input:not([type=checkbox]):not([type=radio]) {
display: block;
margin-top: 0;
width: 100%;
}
.login-form button {
margin-top: 1em;
border: 1px solid #cc6b5a;
background-color: white;
padding: .5em 1em;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Ink</h1>
</header>
<nav>
<ul class="site-nav">
<li><a href="/">Home</a></li>
<li><a href="/features">Features</a></li>
<li><a href="/pricing">Pricing</a></li>
<li><a href="/support">Support</a></li>
<li class="nav-right">
<a href="/about">About</a>
</li>
</ul>
</nav>
<main class="flex">
<div class="column-main tile">
<h1>Team collaboration done right</h1>
<p>Thousands of teams from all over the
world turn to <b>Ink</b> to communicate
and get things done.</p>
</div>
<div class="column-sidebar">
<div class="tile">
<form class="login-form">
<h3>Login</h3>
<p>
<label for="username">Username</label>
<input id="username" type="text"
name="username"/>
</p>
<p>
<label for="password">Password</label>
<input id="password" type="password"
name="password"/>
</p>
<button type="submit">Login</button>
</form>
</div>
<div class="tile centered">
<small>Starting at</small>
<div class="cost">
<span class="cost-currency">$</span>
<span class="cost-dollars">20</span>
<span class="cost-cents">.00</span>
</div>
<a class="cta-button" href="/pricing">
Sign up
</a>
</div>
</div>
</main>
</div>
</body>