一、使用$
標識原生DOM
元素
let $white = document.querySelector('.white')
二、要使用top,left等定位屬性
要先將該元素設置position
屬性,absolute
或者relative
等
三、十種選擇器
三類基礎選擇器:
ID
選擇器;class
選擇器;- 標簽選擇器,
tag
;
以下為延伸的選擇器:
第一種:空格
.container div{
}
這里選擇的是class = "container"
的HTML
元素內的所有div
元素,但是不包括container
這個元素;
第二種:大於號 >
.container > div{
}
選擇的是container
里面第一層的所有div
:
第三種:加號 +
.container + div{
}
選擇的是與container
位於同一層的緊挨着的下一個div
:
注意了,container
同一層緊挨着的下一個元素如果不是div
,那么該選擇器就選擇不到任何元素,例如加一個分行標簽br
進去:
第四種:波浪號 ~
.container ~ div{
}
選擇的是與container
處於同一層級之后的所有div
:
即使同一層下的div
元素中有其他元素隔開,也不影響;
第五種:星號 *
*{
}
選擇的是所有的HTML
元素;
可以與其他選擇器配合使用,比如:
.container ~ *{
}
表示選取與container
同一層下的所有元素;
第六種:屬性過濾器
<a href="https://www.apple.com" title="Apple">Apple</a>
<a href="https://www.google.com">Google</a>
<a href="https://www.facebook.com">Facebook</a>
//1.假如上面有三個超鏈接,給Apple添加一個title屬性,那么就可以通過該屬性選取它
a[title]{
//這樣可以匹配到所有有title屬性的a標簽
}
//2.還可以通過屬性值進行匹配
a[href="https://www.apple.com"]{
//可以選擇到href為蘋果官網的a鏈接
}
//這類似於匹配
a[href^="https"]{
//選擇href屬性值中以https為開頭的a標簽
}
a[href$="com"]{
//選擇href屬性值中以com為結尾的a標簽
}
a[href*="book"]{
//*號會將屬性值book作為關鍵詞匹配,即選擇href屬性值中有book字符的a標簽
}
第七種:偽類選擇器
a:visited //瀏覽過該a鏈接后的狀態
a:hover //鼠標移上a標簽后的狀態
.container div:nth-child(3n+0/n/even) //選擇container下的特定一組div元素;
注意:
.card-container:hover .cover{
transform:rotateY(180deg)
}
//這種情況表示,當懸停在card-container標簽上時,改變.cover的樣式;而不是僅僅局限於選擇card-container這個標簽
要選擇.back
和.cover
兩個標簽不能這樣寫呀:.cover .back
,要這樣寫.cover, .back;
中間要用逗號隔開;
.cover, .back{
width: 100%;
height: 100%;
position: absolute;
backface-visibility: hidden;
//這里寫transition表示之后對.cover和.back標簽樣式所做的修改(如hover)添加一個過渡過程
transition: transform .25s ease-in-out;
}
四、五中常用的CSS單位
px
絕對單位,1px
代表一個像素點,通常修改段落中文字大小時,除了修改font-size
,還要修改line-height
;
em
相對大小;1em=多少px
,是基於目前這個容器中的font-size
大小設定的,取決於使用em
單位的標簽的父標簽(直系),的font-size
;如下圖所示:
上圖中,每一層div
中的1em
值,都取決於上一層div
中的font-size
值;
在用em
單位設置文字段落的字體大小時,只需要修改父元素的font-size
,那么使用em
單位的font-size
和line-height
就不需要更改了,會自動等比例縮放;
rem
也就是root em
。它與em
相似,唯一的不同是它是基於html
元素的font-size
大小來計算的,不受上一級的父標簽影響;
比如上面第一個例子,將em
改為rem
,則不同層(框)內的字體大小不會受到父元素的影響:
優勢為,更容易計算,只需要更改html
標簽中的font-size
即可統一修改所有rem
單位。可以避免元素被多層嵌套后難以預測它的實際大小。
vw與vh
全寫為viewport width
和viewport height
;它們的取值范圍為:1~100
;
當width:100vw
;height:100vh
時,該元素會占滿整個屏幕,當將父元素這樣設置后,就能夠很好地將子元素進行居中處理;
vmin與vmax
vmin
代表屏幕較短的一邊,vmax
代表屏幕較長的一邊,取值也是1~100
;在移動端實現屏幕旋轉顯示。比如:一張正方形的圖片:
<img src="demo.jpg">
img{
width:100vmin;
//width:100vmax;
}
當寬設為100vmin
時,就會以屏幕較短的一邊的總長度作為圖片的邊長,即使旋轉屏幕后,邊長也不會改變;
當寬設為100vmax
時,就會以屏幕較長的一邊的總長度作為圖片的邊長,旋轉屏幕后,邊長也不會改變,不能顯示的區域將會出現滾動軸;
五、Flexbox布局
其他的布局如table
,float
等都不是設計來做網頁布局的,而Flexbox
是第一套專門為了網頁布局而設計的方法。
flex
布局的預設值為block
,所以一開始設置了flex
布局(display:flex
)的元素都會獨占一行。
Flex
布局主要可以分為兩部分:flex-container
(整個彈性盒容器)和flex-items
(彈性盒中的元素);
flex
全屬性實時預覽:http://flexbox.help/
Flex-container(彈性盒)相關屬性
這些屬性寫在設定為flex-container
的標簽中;通過給標簽添加:display:flex
;可以使該標簽成為一個flex-container
。
1.flex-direction
設置flex-container
內的items
的排序方向,默認值為row
(行/水平排序),其他屬性值有:
column
:列/豎直排序;row-reverse
:反向水平排序;column-reverse
:反向豎直排序;
不同的排序方向,主軸與交叉軸不一樣:
2.justify-content
決定主軸的排序方向;有以下屬性值:
center
:主軸上居中;flex-start
:主軸起始方向開始排列(默認表示左);flex-end
:主軸結束方向開始排列(默認表示右);space-around
:空白環繞;space-between
:與around
相似,只不過沒有了最左和最右的空白;space-evenly
:空白平分;
3.align-item
決定交叉軸的排序方向;有以下屬性值:
center
:交叉軸上居中;flex-start
:交叉軸起始方向開始排列(當flex-direction
為默認值row
時,表示上);flex-end
:交叉軸結束方向開始排列;(默認表示下)space-around
:空白環繞;space-between
:與around
相似,只不過沒有了最左和最右的空白;space-evenly
:空白平分;
justify-content:center
與align-item:center
配合使用可以使flex-container
(彈性盒)內的items
水平和垂直方向上居中。
4.flex-wrap
-
當彈性盒內的
item
過多時,該屬性可以控制,是壓縮每個item
寬度不換行,還是保持每個item
寬度換行;-
nowrap:壓縮
item`寬度,不換行; -
wrap
:不改變item
寬度,換行;(換行后,會將彈性盒一分為二,所以兩行item
並不是挨在一起的)
-
5.flex-flow
該屬性為flex-direction
和flex-wrap
組合的縮寫;如:
flex-flow:row wrap;
等效於flex-direction:row;flex-wrap:wrap;
6.align-content
這個屬性的前提條件為flex-wrap
為wrap
時,即有多行flex items
時才會生效;用於設定多行flex-items
間行與行間的對齊方式,屬性值有:
-
flex-start
:在交叉軸開始方向上排列: -
flex-end
:交叉軸結束方向上排列: -
center
:交叉軸中間: -
initial
:默認值,保持原來的樣子: -
space-around
:與上面一樣: -
space-between
:(上下)平均分空白,與around
相似,不過消除了最上和最下的空白: -
space-evenly
:平分空白區域:
Flew Item(盒內元素)相關屬性
1.order
用於調整flex item
(盒內元素)的排序順序,根據order
的值按照主軸方向由小到大排序,默認值為0
;比如C
的order
設置為1
,因為它最大,所以C
排到最后:
2.align-self
該屬性用於復寫flex container
的align-items
屬性;也就是說align-items
是對於全體的flex items
做出規划,而align-self
則是設置個別flex items
的排序方向:
如上圖所示,由於align-items:center;
所以整體的flex items
是居中的,但是,設置了align-self
的C
和D
會按照align-self
的值進行重新排列;
3.flex-basis
該屬性用於設定flex-item
在主軸方向上的大小;比如,當主軸為row
時,可以通過設定該屬性的值來修改每一個flex-item
的寬,這樣flex-item
原來的寬就失效了。
同理,當flex-direction:column;
即主軸為豎直方向時,flex-basis
設定的屬性值將是每一個flex-item
的高;
如果設置為0
的話,相當於將width/height
設置為0
,這樣每個flex-item
在沒有設置overflow:hidden;
的情況下,大小都由內容撐開;
設定為auto
時,則按照原來設定的寬度來計算:
也就是圖中的60px
。
4.flex-grow
該屬性是指在flex-container
主軸方向上有剩余空間的時候,flex item
沿主軸方向擴大的設定。
比如,原來的布局如下圖所示:
將flex-grow:1;
時:
可見flex-item
自動平分了主軸的空白空間。1
的意思是每一個flex-item
都占有主軸空白空間的一份,也就是1/3
。
設定A
的flex-grow:0;
則A
保持原樣,不擴大;將B
的flex-grow:4;
表示先將空白區域分為(4+1+0=6
份)而B
占其中的4
份,C
占1
份也就是:
5.flex-shrink
與flex-grow
效果相反,即當flex-item
超過了主軸長度,沿主軸方向怎樣縮小的設定。默認值為1
,即為了不使flex-item
突出整個flex-box
會自動縮小每個flex-item
。
如圖:當設定每個flex-item
的flex-shrink:0;
時即保持每個flex-item
原來的大小,此時會超出主軸90px
:
如果這樣設定:
.A{flex-shrink: 1}
.B{flex-shrink: 1}
.C{flex-shrink: 1}
即三個flex-item
平分突出的部分,即A
、B
、C
各縮小30px
:
如果這樣設定:
.A{flex-shrink: 1}//share 1/5
.B{flex-shrink: 3}//share 3/5
.C{flex-shrink: 1}//share 1/5
則B
承擔3/5
的突出部分,也就是要縮小90x3/5=54px
,其余兩個flex-item
只需要縮小1/5
,也就是18px
:
6.flex
這個屬性為flex-grow
,flex-shrink
和flex-basis
組合起來的縮寫;
當這樣設定時:
flex:1 1 auto;
//相當於
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
也就是說flex-item
會按照flex-container
(彈性盒)的主軸長度平均分配空間去放大或縮小。
當flex-container
有空白空間的時候,同步擴大:
當flex-container
沒有空白空間時的時候,同步縮小:
再如:
flex: 0 1 150px
此時,flex-grow:0;
即有空白空間時保持原樣,不擴大;整體來講就是只有在flex-container
空間不足時同步縮小,並且固定每個flex-item
在主軸上的長度為150px
。
再如:
flex:0 0 200px
即固定每個flex-item
主軸方向上的長度為200px
,無論flex-container
有無空白空間都不擴大或縮小:
7.關於flex屬性簡寫的問題
當 flex
取值為 none
,則計算值為 0 0 auto
,如下是等同的:
.item {flex: none;}
.item {
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
當 flex
取值為 auto
,則計算值為 1 1 auto
,如下是等同的:
.item {flex: auto;}
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
這就是flex:1的真面目
當 flex
取值為一個非負數字,則該數字為 flex-grow
值,flex-shrink
取 1
,flex-basis
取 0%
,如下是等同的:
.item {flex: 1;}
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
當 flex
取值為一個長度或百分比,則視為 flex-basis
值,flex-grow
取 1
,flex-shrink
取 1
,有如下等同情況(注意 0%
是一個百分比而不是一個非負數字):
.item-1 {flex: 0%;}
.item-1 {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
.item-2 {flex: 24px;}
.item-1 {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 24px;
}
當 flex
取值為兩個非負數字,則分別視為 flex-grow
和 flex-shrink
的值,flex-basis
取 0%
,如下是等同的:
.item {flex: 2 3;}
.item {
flex-grow: 2;
flex-shrink: 3;
flex-basis: 0%;
}
當 flex
取值為一個非負數字和一個長度或百分比,則分別視為 flex-grow
和 flex-basis
的值,flex-shrink
取 1
,如下是等同的:
.item {flex: 2333 3222px;}
.item {
flex-grow: 2333;
flex-shrink: 1;
flex-basis: 3222px;
}
flex
的默認值是以上三個屬性值的組合。假設以上三個屬性同樣取默認值,則 flex
的默認值是 0 1 auto
。同理,如下是等同的:
.item {flex: 2333 3222 234px;}
.item {
flex-grow: 2333;
flex-shrink: 3222;
flex-basis: 234px;
}
實戰案例一:導航欄
<!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>
*{
margin: 0;
padding: 0;
}
ul{
list-style: none;
/* 此時ul成為了flex-container */
display: flex;
justify-content: space-around;
background-color: #eee;
padding: 8px 0;
}
ul > li a{
display: block;
padding: 4px 8px;
}
</style>
<style>
</style>
</head>
<body>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Protfolio</a></li>
<li><a href="#">Contact</a></li>
</ul>
</body>
</html>
效果圖:
實戰案例二:多層Flexbox布局
<!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>
*{
margin: 0;
padding: 0;
}
.post .thumbnail img{
display: block;
width: 100%;
height: auto;
border-radius: 100%;
}
.post .thumbnail{
flex: 0 1 350px;
min-width: 200px;
}
.post{
display: flex;
flex-direction: row;
padding: 2em;
border-bottom: 1px solid #eee;
}
.content{
display: flex;
flex-direction: column;
margin-left: 1.2em;
flex: 1 1 auto;
}
.content h4{
font-weight: bold;
}
.content .excerpt{
font-size: .8em;
color: #666;
}
</style>
</head>
<body>
<div class="post">
<div class="thumbnail">
<img src="http://ahuntsun.gitee.io/blogimagebed/img/vuepress/home/1.jpg" alt="">
</div>
<div class="content">
<h4 class="title"> Flexbox Example</h4>
<div class="excerpt">
The economic downturn in the US triggered by the pandemic has been officially declared a recession.Meanwhile, US markets continued their rebound on Monday, as investors remained optimistic that the downturn will be short-lived.
</div>
</div>
</div>
</body>
</html>
效果圖:
六、Grid布局
布局方式大致有四種:Table
、Float
、Flexbox
、Grid
;
Table
布局是最古老的布局,現在已很少使用。Float
曾經盛行一時,被稱為“DIV + CSS
布局”;而Flexbox
和Grid
才是真正為了網頁布局而設計的;
Flexbox
屬於一維(1-Dimension
)的排版方式,而Grid
則是二維(2-Dimensions
)的排版方式。也就是說一個Flexbox
容器只能控制一個方向,即水平方向或者垂直方向,如果要控制另一方向則需要再添加一層Flexbox
容器;Grid
容器則可以一次過控制兩個方向,這樣就可以直接定義容器中元素的位置了。
通過以下代碼,設置一下布局,通過一張帶標尺的背景圖片可以更直觀地對比:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Grid</title>
<style>
#grid-container{
/* 將父容器(div)設置為grid布局 */
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
/* 將整個grid-container分割成5x5的方格,每格100 x 100 */
/* 該屬性將grid-container分割為五行,每行高100px */
grid-template-rows: 100px 100px 100px 100px 100px;
/* 該屬性將grid-container分割為五列,每列寬100px */
grid-template-columns: 100px 100px 100px 100px 100px;
}
body{
margin: 40px;
}
#ruler{
position: absolute;
top: 0;
left: 0;
width: 580px;
height: 580px;
background-image: url('https://codingstartup.com/assets/grid/grid-ruler.png');
background-size: 580px 580px;
}
.cell-1{
background-color: blue;
}
.cell-2{
background-color: yellow;
}
</style>
</head>
<body>
<div id="ruler"></div>
<div id="grid-container">
<div class="cell-1"></div>
<div class="cell-2"></div>
</div>
</body>
</html>
可以看到預設情況下grid-container
中的元素是這樣排列的;
1.grid-row與grid-column
如果我們想讓藍色的cell-1
占據左上方的四格的話,從圖中可看出,目標范圍為row
方向的1~3
;column
方向的1-3
;可以這樣設置樣式:
.cell-1{
background-color: blue;
grid-row: 1 / 3;
grid-column: 1 / 3;
}
效果為:
如果想讓黃色的cell-2
占據row
方向的4-6
,column
方向的1-3
,則需要這樣設置:
.cell-2{
background-color: yellow;
grid-row: 4 / 6;
grid-column: 1 / 3;
}
效果為:
2.grid-area
該屬性為grid-row
和grid-column
的簡寫,以黃色的cell-2
為例:
.cell-2{
background-color: yellow;
grid-row: 4 / 6;
grid-column: 1 / 3;
//等同於
//grid-area: 4 / 1 / 6 / 3;
}
可以看到,grid-area
的值相當於元素的左上角和右下角的,以(ROW, COLUMN)為形式的坐標。即左上角:(4,1)、右下角:(6,3)。
實際開發時並沒有一把尺來參考,以藍色方塊為例,可以采取下列寫法:
.cell-1{
background-color: yellow;
grid-row: 1 / 4;
grid-column: 2 / span 3;
}
意思為ROW
方向從1~4
,COLUMN
方向上從2
開始,span 3
表示從2開始往COLUMN
方向延伸3格,效果如下:
3.Grid-Lines
如上圖所示,grid-container
中水平和垂直方向上各有6
條線,將整個grid-container
空間分割成了25
份;這些線在CSS Grid
中被稱為Grid Line
。這些Grid Line
是可以命名的。首先給ruler
換一個背景:
#ruler{
position: absolute;
top: 0;
left: 0;
width: 580px;
height: 580px;
background-image: url('https://codingstartup.com/assets/grid/grid-ruler-xy.png');
background-size: 580px 580px;
}
效果為:
也就是將水平方向的Grid Line
命名為X1~X6
;垂直方向的Grid Line
命名為Y1~Y6
;
可以在grid-container
中這樣設置:
#grid-container{
grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
}
設置好Grid Line
名字后,就可以這樣來設置了,以藍色的cell-1
為例:
.cell-1{
grid-row: Y1 / Y4;
grid-column: X2 / X6;
}
上面的代碼表示,ROW
方向范圍為Y1~Y4
之間,COLUMN
方向范圍為X2-X6
之間。
效果為:
4.Grid Areas
grid-container
中的線被稱為grid line
,而方格則稱為Grid Area
;我們也可以直接給特定的格子命名;
在grid-container
中添加多兩個格子cell-3
和cell-4
,分別為橙色和黑色;重置cell-1
,cell-2
的布局,將ruler
換回原來的背景:
//html結果
<div id="grid-container">
<div class="cell-1"></div>
<div class="cell-2"></div>
<div class="cell-3"></div>
<div class="cell-4"></div>
</div>
//css樣式
.cell-1{
background-color: blue;
}
.cell-2{
background-color: yellow;
}
.cell-3{
background-color: orange;
}
.cell-4{
background-color: black;
}
隨后我們可以在grid-container
中添加grid-template-ares
屬性,該屬性的值與grid-container
中的每一個格子一一對應:
#grid-container{
grid-template-areas: "header header header header header"
"nav main main main main"
"nav main main main main"
"nav main main main main"
". footer footer footer .";
}
上面的點表示不給左下角和右下角的格子命名。此時就定義了四個grid-area
分別是:header
、nav
、main
和footer
;
使用方法也很簡單,以藍色的cell-1
為例,在該格子中添加grid-area
屬性,值設置為header
:
.cell-1{
background-color: blue;
grid-area: header;
}
那么cell-1
就占據了grid-area
中名字為header
的區域,也就是第一行:
隨后再分別將cell-2
的grid-area
設置為nav
、cell-3
設置為main
、cell-4
設值為footer
:
.cell-2{
background-color: yellow;
grid-area: nav;
}
.cell-3{
background-color: orange;
grid-area: main;
}
.cell-4{
background-color: black;
grid-area: footer;
}
效果為:
這樣所有的元素都定位到設定好的位置上了;
將ruler
中作為尺的背景圖去掉,就出現了熟悉的布局了:
還可以在grid-container
中通過row-gap
設置行距,column-gap
設置列距;比如都設置為10px
:
#grid-container{
row-gap: 10px;
columns: 10px;
}
效果為:
由於上下左右都多了40px
,隨后將grid-container
的長寬增加40px
就可以了。
5.Fr
Fr
為Grid
中的比例單位,表示占一份的意思。比如:
#grid-container{
grid-template-rows: 300px 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px 100px 100px;
}
//可改寫為
#grid-container{
grid-template-rows: 3fr 1fr 1fr 1fr 1fr;
grid-template-colmn: 1fr 1fr 1fr 1fr 1fr;
}
第二種寫法表示,將grid-container
的row
方向上分為7
份,第一行占3
份,其余四行各占1
份;在column
方向上分成5
份,五列每列占一份。
還可以通過repeat
函數簡寫,該函數第一個參數表示重復幾次,第二個參數表示重復什么,但是該函數不適用於grid-template-areas
。以上設置可改寫為
#grid-container{
grid-template-rows: 3fr repeat(4, 1fr);
grid-template-colmn: repeat(5, 1fr);
}
七、上下左右居中
左右置中
1.display:inline/inline-block
將父元素(容器)設定text-align:center
,就可以左右置中了;
2.display:block
將元素本身的margin-left
與margin-right
設置為auto
,也就是通常的:margin: 0, auto;
就可以左右居中了;
上下左右置中
1.position:absolute
#block{
position:absolute;//使元素浮動,脫離文檔流
top: 50%;
left: 50%;//這樣設置了top和left后,block的左上角就對齊了畫面的中心點
//要將block的中心點與畫面的中心點重合,需要將block向上和左偏移block尺寸的一半,可以采用transform
transform:translateX(-50%) translateY(-50%);
}
//同樣可以采用下列寫法
#block{
position: absolute;
bottom: 50%;
right: 50%;
transform: translate(50%, 50%);
}
2.Flexbox
可以這樣設置,使body
的內容,上下左右居中:
body{
min-height: 100vh;
display: flex; //將body設置為flex-container
justify-content: center; //將主軸上的flex-item居中
align-items: center; //將交叉軸上的flex-item居中
}
3.display Table
原理為將父元素設置為表格布局(display:table
),里面要居中的元素設置為表格的一個格子(display: table-cell
),這樣vertical-align
屬性就能對這個格子生效了;這樣設置:
<body>
<div class="cell"></div>
</body>
body{
display: table;
width: 100%;
min-height: 100vh;
}
.cell{
display: tabel-cell;//此時.cell就會成為表格的一個儲存格
vertical-align: middle;//此時vertical-align屬性就生效了,達到上下居中
text-align: center; //設置左右置中
}
總結:以上三種方法中:
Position:absolute
;對齊的是元素本身,只需要調整需要居中的元素本身即可;- 而第二種(
Flexbox
)和第三種(Table
)方法,對齊的是元素內容。都需要先將父容器調整成與畫面相同的大小(這就是min-height: 100vh;
的作用),然后再設定它的內容(子元素)的對齊方式。
八、Position
position
有五個設定值,分別是:static
、absolute
、relative
、fixed
和sticky
。
Static
HTML
里面所有元素的Position
默認值都是static
,設定了該屬性的元素,不會脫離文檔流,會隨着HTML
文檔排版的流程(flow
)而發生變化。
首先,搭建以下的HTML
和CSS
樣式:
效果為:
為了方便說明,事先為
static
類添加了樣式(下同);
隨后在html
樣式中新增一句"Hello World"
:
Hello World
<div class="static"></div>
可以看到這個static
的div
就會因為這一行文字而向下移動了一點:
再次改寫HTML
和CSS
樣式:
//HTML結構
<div class="height"></div>
<div class="static"></div>
//CSS結構
.static{
position: static;
width: 360px;
height: 360px;
}
.height{
width: 750px;
height:120px;
}
效果如下:
可以看到,height
div高為120px
,所以static
的div就要相應下移120px
;
注意:position
值為static
的元素對於top
、left
、right
、bottom
的設定值都是不會生效的;
Absolute
如下改寫HTML
和CSS
結構:
//HTML結構
<div class="height"></div>
<div class="absolute"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.absolute{
position: absolute;
width: 240px;
height: 240px;
right: 80px;
bottom: 60px;
}
效果為:
如圖所示,right
的設定值是將元素定位到與HTML
文檔右邊相距80px
的位置;bottom
則是將元素定位到與HTML
文檔底部相距60px
的位置。
absolute
元素會固定在所設定的位置,不會隨着HTML文檔排版的流程移動,即脫離文檔流。
更改樣式,加多幾個高度為120px
的藍色height
div:
//HTML結構
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="absolute"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.absolute{
position: absolute;
width: 240px;
height: 240px;
right: 80px;
bottom: 60px;
}
效果:
可以看到並沒有影響到absolute
元素所在的位置的。但是如果absolute
元素所在的容器有滾動軸的話,它就會隨着滾動軸移動:
再次更改樣式,添加多一個absolute
div:
//HTML結構
<div class="height"></div>
<div class="absolute"></div>
<div class="absolute"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.absolute{
position: absolute;
width: 240px;
height: 240px;
right: 80px;
bottom: 60px;
}
乍一看頁面沒有發生變化:
但是,實際上兩個absolute
元素是重疊到一起了。可以通過將其中一個absolute
元素的right
設定為100px
,證明:
<div class="absolute" style="right: 100px"></div>
可以看到這兩個absolute
元素確實是重疊在一起的:
再次更改樣式,將absolute
元素放在absolute
元素內,結果會如何呢?
//HTML結構
<div class="height"></div>
<div class="absolute">
<div class="absolute"></div>
</div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.absolute{
position: absolute;
width: 240px;
height: 240px;
right: 80px;
bottom: 60px;
}
結果是里面的absolute
元素的right
與bottom
是根據外面那層的absolute
元素的位置去定位的。所以會再向左偏移80px
,向上多偏移60px
:即absolute是根據外層非static元素定位的,包括fixed;
Relative
新增一個relative
div並改寫樣式:
//HTML結構
<div class="height"></div>
<div class="relative"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.relative{
position: relative;
width: 360px;
height: 360px;
top: 60px;
left: 150px;
}
效果如圖所示:
可見,relative
與static
是很相似的,都是會跟隨HTML
的排版流程(文檔流)移動。但是它比Static
多了top
、left
、right
、bottom
的設定。也就是說,它在跟隨HTML
排版流程去定位之余,還可以通過這四個值進一步調整位置。
比如在上面增加一個height
div:
//HTML結構
<div class="height"></div>
<div class="height"></div>
<div class="relative"></div>
relative
元素就會因上方增加的內容而向下移動:
除此之外,relative
最重要的一個功能是:在它里面的absolute
元素會根據relative
的位置去定位;比如在它里面加一個absolute
div:
//HTML結構
<div class="height"></div>
<div class="height"></div>
<div class="relative">
<div class="absolute"></div>
</div>
會發現absolute
元素的right
與bottom
是根據relative
元素的位置去定位的:
有人可能會認為這不是很正常嘛,我們將relative
改成static
:
//HTML結構
<div class="height"></div>
<div class="height"></div>
<div class="static">
<div class="absolute"></div>
</div>
可以看到,absolute
元素會直接無視包含它的static
元素:
總結:relative
相對於static
,主要增加了兩大功能:
-
第一:
relative
具備了top
、left
、right
、bottom
的設定; -
第二:可以使
absolute
子元素根據它的位置去定位,也就是子絕父相;
Fixed
新增一個fixed
div:
//HTML結構
<div class="height"></div>
<div class="height"></div>
<div class="fixed"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.fixed{
position: fixed;
width: 240px;
height: 240px;
bottom: 60px;
left: 80px;
}
效果為:
fixed
與absolute
是很相似的,不同的地方有兩點:
-
第一:
fixed
會固定到熒幕中的固定位置,即使滾動頁面,它的位置也不會發生改變,是脫離文檔流的,再標准流中不占空間;增添多個
height
div,可以發現即使滾動頁面,fixed
div位置也不變: -
第二:如果
fixed
div設定了top
、left
、bottom
、right
的值,即使將它放入relative
div中,fixed
div 依舊會根據頁面,也就是body
去定位,而不會根據relative
div去定位。改寫樣式,在
relative
div 中添加一個fixed
div://HTML結構 <div class="height"></div> <div class="relative"> <div class="fixed" style="position: fixed; width: 50px; height: 50px; background-color: #000"></div> </div>
在
fixed
div不添加top
、left
、bottom
、right
屬性時,fixed
div 會相對於包裹它的relative
div 定位:當設定了
top
、left
、right
、bottom
其中一些屬性之后://HTML結構 <div class="height"></div> <div class="relative"> <div class="fixed" style="position: fixed; width: 50px; height: 50px; background-color: #000; top: 50px"></div> </div>
fixed
div 就會脫離包裹它的relative
div 的束縛,而根據body
進行定位:
Sticky
添加sticky
div 改寫樣式:
//HTML結構
<div class="height"></div>
<div class="sticky"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
//CSS結構
.height{
width: 750px;
height:120px;
}
.sticky{
position: sticky;
width: 240px;
height: 90px;
top: 0;
}
可以看到,頁面出現了滾動軸:
隨后滾動頁面:
可以發現,sticky
div 在滾動的過程中,當貼到頁面頂部的時候,就會固定在頁面頂部,也就是"粘住了";之所以會粘住是因為我們設置了sticky
div 的top
為0
,當它距離頁面頂部0px
的時候,就會觸發top:0px;
這一屬性。
九、Block,Inline和Inline-Block
HTML
元素大致上默認分為兩種形態,一種為Block
,另一種為Inline
。Block
為區塊的意思,Inline
為內聯的意思。
1.Block
Block
元素會獨占一行,比如兩個段落,即使源碼中沒有空格,顯示的兩段文字也會隔開(因為p
標簽是塊元素):
由於塊元素是獨占一行的,所以,即使一行中有空間也不允許兩個塊元素左右排列,如下圖所示將p
標簽的寬度設置為50%
后,兩個P
標簽也不會左右排列。
HTML
源碼中會將多個空格合並為一個空格進行顯示,若要加多個空格可以添加: (no-break-space)
Block
元素的特點為:
- 單獨占一行,
Block
元素之間只能上下排列; - 元素大小可以通過
width
和height
設定;
常見默認為Block
的標簽有:div
、p
、h1
到h6
、ul
等。
2.Inline
如下圖所示,在p
標簽中加入 strong
標簽,並設置樣式:
這里的 strong
就是inline
內聯元素。它的特點為:
Inline
標簽之間可以左右排列;inline
元素的大小由所包含的內容決定,不受width
和height
影響;
常見默認為inline
的標簽有 a
、 strong
、 span
等。
3.Inline-Block
它結合了Inline
和Block
兩者的特性,既可以設定寬度和高度,又可以與其他Inline
元素並排。
比如在段落的最后面加一個超鏈接按鈕,就可以采用Inline-Block
:
樣式為:
//HTML
<p>
//some words
<a href="#">More...</a>
</p>
//CSS
a{
display: inline-block;
width: 80px;
height: 40px;
line-height: 40px;
text-align: center;
background-color: black;
color: white;
border-radius: 4px;
text-decoration: none;
}
效果如下,這樣就可以賦予本身為內聯標簽的a
標簽以塊級標簽特性了:
4.對齊方式
所有HTML
元素都可以通過更改display
屬性將它設置為Blcok
、Inline
、Inline-Block
;
改寫如下樣式:
//HTML
<div>Block</div>
<span>Inline</span>
<br>
<strong>Inline-block</strong>
//CSS
div{
width: 50%;
}
span{
}
strong{
display: inline-block;
}
div, span, strong{
background-color: black;
color: white;
}
效果如下:
隨后給body添加樣式:
body{
text-align: center
}
可以看到Inline
與Inline-Blick
元素都水平居中了,而block
元素只是將里面的文字居中了,block
元素本身並沒有居中:
這是因為Inline與Inline-Blick二者的容器的大小都是由內容決定,所以text-align:center
對整個元素都有效;而對Block
元素無效,只對該元素內部的文字有效。要想讓block
元素和其中內容都居中,需要設置block
元素的margin
樣式:
div{
width: 50%;
margin-left: auto;
margin-right: auto;
}
此時就能達到水平居中了:
總結:居中方法:
-
Inline與Inline-Blick:
body{ text-align: center }
-
Block:
body{ text-align: center } div{ width: 50%; margin-left: auto; margin-right: auto; }
十、Box Model
CSS Box Model
一共包括了四種屬性:Content
、Padding
、Border
和Margin
。
它們的結構和排序順序是這樣的:
由內往外分別是:content
、padding
、border
、margin
。
關於margin
與padding
:
- 一個屬性值時:上下左右;
- 兩個屬性值時:上下, 左右;
- 三個屬性值時:上,左右,下;
- 四個屬性值時:上、右、下、左;(順時針)
1.標准盒子模型
在標准盒子模型中,Width = content
;
也就是說只要改變了content
、padding
、border
、margin
中的任一個值,都會撐大整個盒子。
2.怪異(IE)盒子模型
在怪異盒子模型中,Width = content + padding + border + margin
;
一旦設置了元素的width
大小后,相當於固定了整個盒子的大小。再去改變上面的四個屬性,盒子整體的大小不變,四個屬性自動調整。
利用這一特性,就可以隨便更改盒子的margin
、content
、padding
、border
屬性值而不用擔心撐大盒子了。
盒子默認為標准盒子模型,即box-sizing:content-box;
可以通過:box-sizing:border-box
,來將它設置為怪異盒子模型。
3.Inline元素使用margin與padding
- 使用
margin
時:只會左右生效,上下會失效:
-
使用
padding
時:上下左右都生效,只不過只有左右隔開了,改變了布局;上下沒有改變布局,只是覆蓋了:
可以這樣記憶,inline
元素的margin
和padding
屬性都不會影響垂直方向上的布局。
4.inline-block使用margin與padding
inline-block
元素的margin
和paddind
屬性在上下左右四個方向上都會生效:
5.關於margin-top與margin-bottom折疊問題
上下排列的兩個塊級元素,分別設置margin-bottom
和margin-top
;整體的空隔取二者的最大值,而不會疊加;解決方法為:在中間加入一個有高度的元素,比如1px
的border
(通常通過為元素::after
添加);
十一、瀑布流
先來看看采用瀑布流布局的典型例子:Pinterest
:世界上最大的圖片社交分享網站。
最簡單實現的方法是使用別人寫好的插件比如:
-
Masonry.js
-
lsotope.js
它們實現的原理是通過javascript
計算一共有多少個方格,在計算每一個方格的寬度和高度,因容器的寬度可以放置多少列等等要求。將全部方格的position
都設置為absolute
,逐一計算它們的top
和left
實現定位。
由於所有方格的位置是計算出來的,當頁面寬度變化時可以實現動態地重新排列。
下面介紹使用純CSS
實現瀑布流的兩種方法,並分析它們的限制:
1.CSS Column
方法一:僅適用column-count
和column-gap
兩個屬性實現
代碼為:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Column 實現瀑布流布局</title>
<style>
body{
margin: 4px;
font-family: Helvetical;
}
.masonry{
column-count: 4;
column-gap: 0;
}
.item{
padding: 2px;
position: relative;
/*給每張圖片加上編號*/
counter-increment: item-counter;
}
.item img{
display: block;
width: 100%;
height: auto;
}
/*給每張圖片加上編號*/
.item::after{
position: absolute;
display: block;
top: 2px;
left: 2px;
width: 24px;
height: 24px;
text-align: center;
line-height: 24px;
background-color: #000;
color: white;
content:counter(item-counter)
}
</style>
</head>
<body>
<!-- 方法一:僅適用column-count和column-gap兩個屬性實現 -->
<div class="masonry">
<!-- 通過picsum獲取隨機圖片,並隨機設置一下每張圖片的尺寸 -->
<div class="item">
<img src="https://picsum.photos/360/460?random=1" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/320/260?random=2" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/100/160?random=3" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/310/400?random=4" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/260/360?random=5" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/370/480?random=6" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/320/260?random=7" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/330/440?random=8" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/150/220?random=9" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/230/230?random=10" alt="">
</div>
</div>
</body>
</html>
效果為:
優點:代碼簡單,只需要使用column-count
和column-gap
兩個屬性即可;
缺點:圖片的排列順序是從第一列的上到下,再到下一行的上到下;
2.Flexbox
沿用第一種方法的HTML
結構,更改樣式如下:
body{
margin: 4px;
font-family: Helvetical;
}
.masonry{
/* 這樣設置后,圖片組成的flex-item高度超過1000px就會換一列,向右排列 */
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 1000px;
}
.item{
position: relative;
width: 20%;
padding: 2px;
box-sizing: border-box;
/* 為每個item加上編號 */
counter-increment: item-counter;
}
.item img{
display: block;
width: 100%;
height: auto;
}
/* 為每個item加上編號 */
.item::after{
position: absolute;
display: block;
top: 2px;
left: 2px;
width: 24px;
height: 24px;
text-align: center;
line-height: 24px;
background-color: #000;
color: white;
content:counter(item-counter)
}
此時效果與第一種方法一致:
不過,可以通過flex
布局中的order
屬性,更改它的排序順序。添加如下樣式:
body{
margin: 4px;
font-family: Helvetical;
}
.masonry{
/* 這樣設置后,圖片組成的flex-item高度超過1000px就會換一列,向右排列 */
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 1000px;
}
.item{
position: relative;
width: 25%;
padding: 2px;
box-sizing: border-box;
/* 為每個item加上編號 */
counter-increment: item-counter;
}
.item img{
display: block;
width: 100%;
height: auto;
}
/* 為每個item加上編號 */
.item::after{
position: absolute;
display: block;
top: 2px;
left: 2px;
width: 24px;
height: 24px;
text-align: center;
line-height: 24px;
background-color: #000;
color: white;
content:counter(item-counter)
}
/* 選取第一行的item,當n=0~3時,可以選取到1、5、9、13 */
.item:nth-child(4n+1){
order: 1;
}
/* 選取第二行的item,當n=0~3時,可以選取到2、6、10、14 */
.item:nth-child(4n+2){
order: 2;
}
/* 選取第三行的item,當n=0~3時,可以選取到3、7、11、15 */
.item:nth-child(4n+3){
order: 3;
}
/* 選取第四行的item,當n=0~3時,可以選取到4、8、12、16 */
.item:nth-child(4n){
order: 4;
}
效果為:
這種方法主要使用了Flex
中的order
屬性;
存在的問題:需要設置Flex
容器的高度。所以我們需要知道內容加起來的高度是多少。還要考慮要分為多少個豎行。去為Flex
容器計算一個合理的高度。比如改變頁面的寬度,會出現只需要三個豎行就能容納圖片的情況:
而這種情況我們是不希望看到的;
綜上所述:要實現瀑布流簡單時可以使用column,完美實現時還需采用js套件。
十二、Float
元老級的布局屬性,幾乎不存在兼容性問題,連IE6
也支持。
Float
最初是為了解決"繞圖排文"問題設計的。不使用Float
時:
<img src="https://picsum.photos/200/200"/>
<p>一段文字</p>
效果為:
為加上
float
屬性就可以實現"繞圖排文"了:
img{
float:left;// 脫離文檔流
display: block;// join文檔流
margin-right:20px;
}
1.清除浮動
設置樣式:
//HTML
<div class="container">
<div class="left">一段文字</div>
<div class="middle">一段文字</div>
<div class="right">一段文字</div>
</div>
<p>
一段文字
</p>
//CSS
.left .middle .right{
background-color:yellow;
}
.right{
float:left;
width:33.3%;
}
.left{
float:left;
width:33.3%;
}
.right{
float:left;
width:33.3%;
}
此時的效果為(大致):
三個浮動的div
並沒有因為被container
div 包裹着而與p
標簽隔開,這是因為,三個div
都浮動起來了,與container
div 不在一個平面上。就好像橡膠圈一樣container
捆不住這些浮動的div
,所以會出現這樣的情況,即container
div 出現了元素坍塌;
為了恢復正常就需要清除父容器container
div 中子元素的浮動了,有以下三種方法:
-
第一:clearfix
這個類的作用為結束
float
繼續影響后續內容的排版;使用方法為在父容器container
div 同一層加上一個塊級元素,再添加如下的樣式://HTML <div class="container"> </div> <div class="clearfix"></div> //CSS .clearfix{ clear:both; }
現在,排版就正確了:
這種方式並不優雅,不通過添加
HTML
塊級標簽,而是通過偽類after
的方式添加,樣式如下://HTML <div class="container"> </div> //CSS .container::after{ content: ''; clear:both; display:block; }
-
第二:overflow
只需要將父容器
container
div 的overflow
屬性設置為visible
以外的任何一個值,比如auto
或hidden
。//HTML <div class="container"> </div> //CSS .container{ overflow:auto; }
此時這個
container
div 就會變成一個BFC
(Block Formatting Context
:塊級可視化上下文),BFC
會形成一個局部的塊級,達到"隔斷"的效果。 -
第三:display
為父容器
container
div 添加display:flow-root;
即可將其變成一個BFC
。//HTML <div class="container"> </div> //CSS .container{ display: flow-root; }
不過這個屬性較新,並且所有的IE版本都不支持:
十三、響應式(Responsive)布局
響應式布局指的是網頁會因不同設別的屏幕大小,例如電腦、手機、平板等設備。自動調整版面布局,圖片及字體大小等。使網頁適應在不同大小的熒幕下顯示。
分別有以下幾個方面:
1.Media Query(媒體查詢)
可以通過設置Media Query
的Breakpoint
(斷點),並且設置當符合這個Breakpoint
的時候,改變CSS
樣式。
@media語法:
@media[mediatype][and|not|only]([mediafeature]){
/*css code*/
}
常用mediatype
- all 用於所有設備
- print 用於打印機和打印預覽
- screen 用於電腦屏幕、平板、智能手機等
常用mediafeature
- max-width 輸出設備中頁面最大可視區域寬度 小於這個width時,其中的css起作用
- max-height 輸出設備中頁面最大可視區域高度 小於這個height時,其中的css起作用
- min-width 輸出設備中頁面最小可視區域寬度 大於這個width時,其中的css起作用
- min-height 輸出設備中頁面最小可視區域高度 大於這個height時,其中的css起作用
- -webkit-min-device-pixel-ratio 設備上最小的物理像素和設備獨立像素比,簡稱設備像素比(DPR )
例如:
@media screen and (max-width: 360px){
}
在上面的設定中,screen
指有屏幕的設備;max-width: 360px
表示Query
或是叫Breakpoint
,指屏幕最大寬度為360px
;通過and
組合起來就是:當設備有屏幕,並且最大寬度為360px
以下的情況下,觸發花括號內的CSS
樣式。
還可以設置屏幕寬度較寬時的樣式:
@media screen and (min-width: 960px){
}
上述設置指的是,屏幕寬度大於960px
的情況下觸發花括號內的CSS
。
至於Breakpoint
應該如何設定,各個CSS
框架有自己的規定:
-
tailwindcss
// tailwind.config.js module.exports = { theme: { screens: { 'sm': '640px', // => @media (min-width: 640px) { ... } 'md': '768px', // => @media (min-width: 768px) { ... } 'lg': '1024px', // => @media (min-width: 1024px) { ... } 'xl': '1280px', // => @media (min-width: 1280px) { ... } } } }
tailwindcss
將Breakpoint
設置為了640px
、768px
、1024px
、1280px
; -
Bootstrap
/* 超小屏幕(手機,小於 768px) */ /* 沒有任何媒體查詢相關的代碼,因為這在 Bootstrap 中是默認的(還記得 Bootstrap 是移動設備優先的嗎?) */ /* 小屏幕(平板,大於等於 768px) */ @media (min-width: @screen-sm-min) { ... } /* 中等屏幕(桌面顯示器,大於等於 992px) */ @media (min-width: @screen-md-min) { ... } /* 大屏幕(大桌面顯示器,大於等於 1200px) */ @media (min-width: @screen-lg-min) { ... }
Bootrap
將Breakpoint
設置為了768px
、992px
、1200px
;
2.Meta Viewport
它是一個寫在HTML
head 標簽里面的 meta
標簽。這個設定是為了告訴手機瀏覽器,將網頁的寬度設定為手機屏幕的寬度。
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
這個標簽是告訴手機瀏覽器,這個網頁是支持響應式的。只有加上了這個標簽媒體查詢(Media Query
)對於小屏幕寬度的設定才會生效;
3.Resolution(解像度)
如果你的顯示器不是高清的,解像度設置為1920 x 1080
;則表示屏幕橫向由1920
個點組成,縱向由1080
個點組成。
而如果是高清屏幕,一個單位解像度就是有多個點組成的。
為了在屏幕中顯示足夠清晰的圖片,就需要將圖片的尺寸放大兩倍到三倍;
4.Image Size
如何做到在屏幕中顯示高清圖像?最簡單的做法就是將600px * 600px
的圖片以300px * 300px
的大小顯示。
為了顯示高清圖像,我們可以提供同一張圖片的三種尺寸(1x
、2x
、3x
)。比如顯示圖片的框大小為300px * 300px
:
<picture>
<source srcset="https://placehold.it/600x600 2x, https://placehold.it/900x900 3x">
<img src="https://placehold.it/300x300">
</picture>
這樣設備就會根據高清支持程度加載對應的尺寸的圖片了,如支持2x
高清顯示的就加載尺寸為600px * 600px
的圖片;
5.Font-Size
當屏幕大小發生變化時,字體大小也應該跟着變化。所以推薦使用相對單位rem
和vh/vw
;
部分參考自CodingStartup起碼課