如果說網頁是一棟大樓,HTML 是他的骨幹(鋼筋水泥),那 CSS 就是裝潢了。
CSS 是 Cascading Style Sheets(階層式樣式表)的縮寫,顧名思義它就是用來更改樣式的。
改變樣式的三種方式
有三種方式可以改變樣式:
(1)加在 tag 裡面
<div style="background: red;">
hello
</div>
(2)加在 head 中
格式為:
<head>
<style>
selector {
attribute: value;
}
</style>
</head>
所以可以寫成
<head>
<style>
div {
background: red;
}
</style>
</head>
<body>
<div>
hello
</div>
</body>
(3)開一個css檔案再引入
@index.html
<head>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div>
hello
</div>
</body>
@index.css
div {
background: yellow;
}
第三種方式在維護上會比前兩種容易。
CSS selector
要先選到你想改變的東西才能改變,這很好懂,所以這部分就是要講怎麼選到你要的元素。
第一個要說 universal selectors
* {
color: white;
}
使用*
就可以選到所有 HTML 的元素
或是可以使用標籤名稱
div {
background: yellow;
}
這樣可以選到所有 div
標籤。
但通常我們不會選所有標籤,常用的方法是使用 id or class。
id 只會有一個,不會重複;而 class 可以有很多個,同一個 tag 裡面可以有不只一個 class。
@index.html
<div id="hello1">
hello1
</div>
<div class="bg-yellow">
hello2
</div>
<div class="bg-yellow text-green">
hello3
</div>
@index.css
#hello1 {
background: green;
}
.bg-yellow {
background: yellow;
}
.text-green {
color: green;
}
那能不能同時符合多個條件才執行?
條件要連著寫,不能有空格,像是以下:
@index.html
<span class="bg-yellow">
hello1
</span>
<div class="bg-yellow">
hello2
</div>
<div class="bg-yellow text-green">
hello3
</div>
@index.css
span.bg-yellow {
background: yellow;
color: red;
}
.bg-yellow {
background: yellow;
}
.bg-yellow.text-green {
background: yellow;
color: green;
}
剛剛講的都是同一階層,那如何去調整下面的階層?
a > b
表示這個效果是對 a 下面那一層的 b
a b
表示這個效果是對 a 下面所有的 b
@index.html
<div class="lv1">
lv1
<div class="lv2">
lv2-1
<div class="bg-yellow">
lv3
</div>
</div>
<div class="bg-yellow">
lv2-2
</div>
</div>
@index.css
.lv1 > .bg-yellow {
background: yellow;
}
這邊只有 lv2-2 會變黃色
.lv1 .bg-yellow {
background: yellow;
}
這邊 lv3 和 lv2-2 都會變黃色
接下來要介紹 ~
和 +
a ~ b
表示這個效果是對 a 同一層下面所有同一層的 b
a + b
表示這個效果是對 a 同一層所有符合 a 下面緊鄰的 b
@index.html
<div class=“b”>1</div>
<div>2</div>
<div class="a">3</div>
<div class="b">4</div>
<div class="b">5</div>
@index.css
.a ~ .b {
background: red;
}
4 & 5 會是紅色
.a + .b {
background: red;
}
4 會是紅色
pseudo-classes
另外還有 pseudo-classes,例如::hover
,當做到指定動作時才會觸發。
但因為必須要觸發才會有效果,所以如果需要 debug 會很麻煩。
此時可以使用 檢查 > element > 先按到想要 debug 的那個 HTML 程式碼 > 下面的style > toggle element state > 可以讓他維持在那個狀態下。
nth-child
接下來要講一個很有趣的 selector 叫 nth-child
@index.html
<div class="wrap">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
@index.css
.wrap div:first-child {
background: red;
}
第一行就會變成紅色,如果用
last-child
,最後一行就會變紅色。
如果改成以下:
.wrap div:nth-child(3) {
background: red;
}
就能指定第三行,如果(odd)就是奇數,(even)就是偶數,也可以用數字帶(3n)就是 3 的倍數,(2n+1)就是奇數。
那如果我們稍微改一下
@index.html
<div class="wrap">
<div>1</div>
<div class="bg">2</div>
<div>3</div>
<div class="bg">4</div>
<div>5</div>
</div>
@index.css
.wrap .bg:nth-child(1) {
background: red;
}
照理說應該是第二行會變色吧!但實際上是不會有顏色出現,原因是這邊會先去找第一行,再看他有沒有 bg 這個 class,條件符合才會顯現。
所以如果要讓第二行出現顏色要改成:
.wrap .bg:nth-child(2) {
background: red;
}
pseudo-element
前面有講到 pseudo-classes,這邊要講的是
pseudo-element(偽元素)
直接示範比較好懂
@index.html
<div class="wrap">
1000
</div>
@index.css
.wrap::before {
content: '$';
color: red;
}
就會得到 $ 1000,$ 會是紅色的
可以直接創造內容,這就是為什麼叫做偽元素的原因
同理,::after
就是會出現在後面
.wrap::after {
content: ‘NTD’;
color: red;
}
其實 content 除了自己輸入外,還有其他方法
@index.html
<div class="wrap">
1000
</div>
@index.css
.wrap::before {
content: attr(class);
color: red;
}
就會印出 wrap 1000
我們也可以自訂元素,而通常都是以data
開頭
但要content
要記得寫,不然都不會生效
@index.html
<div class="wrap" data-symbol="$">
1000
</div>
@index.css
.wrap::before {
content: attr(data-symbol);
color: red;
}
權重
最後要講到 CSS selector 的權重。
基本規則就是 id > class(class, pseudo-class, attribute) > tag
可以把他看做三組數字比較,由左至右比較,第一個贏就贏了,平手才往下繼續比。
0, 1, 0
.wrap {
color: red;
}
0, 3, 2
div.wrap > div.list > .item {
color: blue;
}
1, 0, 0
#price {
color: pink;
}
所以就是 pink,如果數字都一樣,後者勝。
但除了這三個之外還有兩個權重更高的。
第一個是 inline style
,就是直接寫在 tag 裡面
<div class="wrap">
<div class="list">
<div class="item" id="price" style="color: aqua;">
1000
</div>
</div>
</div>
權重為 1, 0, 0, 0
第二個是 !important
,可以覆蓋掉所有
1, 0, 0, 1, 0
.wrap {
color: red !important;
}
0, 3, 2
div.wrap > div.list > .item {
color: blue;
}
1, 0, 0
#price {
color: pink;
}
但這兩種很少使用,因為會使專案維護變得困難
另外要注意,為什麼數字之間要有逗號而不是直接變成數字呢?那是因為如果你沒有逗號的話會很容易誤解,像是用了 12 個 class 會變 120,用了一個 id 會變 100,你會以為 class 會蓋掉 id,但其實不是的,因為權重是:
12 個 class: 0, 12, 0
1 個 id: 1, 0, 0
意思是說無論你有幾個 class,你都不可能蓋掉 id,因為 id 權重永遠都比 class 高,不是逢十就能進位。
補充:
CSS Specificity (CSS 權重一覽)
你对CSS权重真的足够了解吗?
各種裝飾
你已經可以靠著前面說的一大堆方法選到你要的元素了,選到之後就要來改變他的各種狀態啦。
背景
第一個要說 background,有幾種方法
(1)直接填顏色
.box {
background: red;
}
(2)填色碼
.box {
background: #f0f0f0;
}
(3)rgb
.box {
background: rgb(244, 0, 128);
}
(4)rgba (a 是透明度,數值是 0~1)
.box {
background: rgb(244, 0, 128, 0.5);
}
(5)除了顏色之外也可以用圖片
.box {
background: url(圖片位置);
}
如果這時候你看不見整張圖片,可以透過設定 width
& height
的方式調整,但如果你的長寬設的比圖片還大,這時候可能你會發現圖片重複了。
如果不想要重複請加上 no-repeat
.box {
background: url(圖片位置) no-repeat;
width: 500px;
height: 500px;
}
那如果你的長寬設不夠時,此時只會顯示圖片的一部份,但這時候我可能只想要圖片的正中央怎辦?
.box {
background: url(圖片位置) no-repeat center center;
width: 50px;
height: 50px;
}
第一個是 y軸,第二個是 x軸,所以同理想要右下角就是 bottom right
到目前為止都是修改我們範圍的長寬,圖片都是原本 size
那可以直接修改圖片大小嗎?
background-size: 300px 200px;
這邊也可以設為 %
background-size: 100% 100%;
這時就會去符合我們設定的長寬了
還有兩個很常用的,一個是 contain
background-size: contain;
他會自動對齊可以對齊的長或寬,重點是可以看到整張圖片&比例和原圖一樣。
另一個是 cover
background-size: cover;
他會使圖片佔滿你目前的長寬(你拉動瀏覽器他會動態填滿),但圖片顯示的範圍也會動態調整。
還有很多其他屬性可以透過,檢查 > 找到你要的 background > 有個箭頭點下後可以看到。
border & padding & margin
接著要說 border,也就是邊框。
要注意 border 是會影響整體寬高的
.box {
background: red;
width: 30px;
height: 30px;
border: 10px solid green;
}
所以這裡的寬就是 30 + 10 + 10 = 50px
border-style
可以調邊框的樣式
覺得邊框不夠圓滑嗎?可以用 border-radius
.box {
background: red;
width: 30px;
height: 30px;
border: 10px solid green;
border-radius: 50%;
}
設成 50% 就會剛好是圓形
既然可以畫出圓形,那三角形可以嗎?
將 border 的四個邊設成不同顏色,就可以發現其實形狀會是梯形,當 width & height 為 0 時,四個邊就會變成四個三角形了。
只要將其中三個邊顏色設為 transparent
,三角形就出現了。
\
有一個跟 border 很像的是 outline
,差別在於 outline 是往外擴張,並不會影響整體寬高。
outline: 5px solid green;
但其實實際開發上並不常用到。
再來是 padding
& margin
其實跟剛剛的 border
& outline
很像,這邊就是邊距的意思,padding
往內推,會影響整體寬高;margin
則是往外推。
我們這邊可以看到 Chrome 瀏覽器在我們還沒做任何事時,就會自動先幫我們加上邊距
若要去除,可以加上:
body {
margin: 0px;
}
reset.css vs normalize.css
https://ithelp.ithome.com.tw/articles/10196528
文字相關
接下來要講和文字相關的 CSS
.box {
color: grey;
font-size: 30px;
font-weight: bold;
font-family: fantasy;
letter-spacing: 2px;
line-height: 1.5em;
text-align: center;
}
font-size
在瀏覽器最小就是 12px
font-weight
也可以用數字 100~900
font-family
如果有支援就可以用,沒支援就會跳回預設的
letter-spacing
字距
line-height
可以用 px
,也可以用 em
,1.5em 就是 1.5 倍行高的意思
text-align
可以調置左置中置右
em
以母元素的基礎字體大小作為倍數的單位
ex: 母元素 12px, 1em = 12px, 2em = 24px
rem
以根元素的基礎字體大小作為倍數的單位
ex: 1rem = 12px
//那如果高度也要置中呢?這邊有個小技巧
如果只有一行字,line-height
調成跟 height
一樣即可
如果有多行字,可以先把 height
刪掉,再使用 padding
去推
除了上面這些外,當你有設定寬,而文字太長超過寬度時,他會換行
word-break
就是決定斷句的位置
word-break: break-all;
break-all
是到寬度就直接換
break-word
是到寬度而文字擺不下時,將該文字移到下一行
另一個是 white-space
,預設的時候不管你空白或換行,都只算一個空白而已
white-space: nowrap;
//nowrap
就是不要將文字包起來,效果就是文字不換行
white-space: pre;
//會保留你在程式碼的空白&換行
white-space: pre-line;
//會保留換行
OK,那文字超出去,可以藏起來嗎?
這邊就要使用 overflow
了
overflow: hidden;
//hidden
可以將超出的東西隱藏(不只有針對文字),scroll
會有拉軸滑動
另一個很像的是 text-overflow
,是針對文字使用的
text-overflow: ellipsis;
//ellipsis
可以將超出的字變成...
但如果要造成這個效果必須滿足幾個條件:
要先用 white-space: nowrap
讓字不換行,這不換行的字還要超出 width
,超出的字要 overflow: hidden;
,才會出現 text-overflow: ellipsis;
這個效果。
transition
當你做了會改變狀態的事,如 :hover
等等
滑鼠移過去時,會瞬間變化,那要如何做出『漸變』呢?用 transition
#price {
width: 150px;
height: 150px;
border: 10px solid green;
border-radius: 50%;
font-size: 30px;
font-family: fantasy;
line-height: 150px;
text-align: center;
transition: all 0.6s ease-in-out;
}
#price:hover {
color: white;
background: grey;
border: 10px solid grey;
}
transition
有三個參數(對哪個屬性作用, 幾秒, 預設的漸變動畫)
這邊要注意如果把
transition
放在:hover
那邊,放開時會失去transition
的效果。
transform
最後要講到 transform
,這是一個有很多功能的裝飾。
例如 transform: scale(2);
以中心放大兩倍
transform: rotate(180deg);
就會轉180度
所以搭配 transition
可以製造出很多效果。
還有 transform: translate(50px, -20px);
就會往右移 50px,往下移 20px
那你會想這有什麼用,不是可以用 position 就可以更動了嗎?
其實不然,translate
他不會影響其他元素,所以在動畫裡要移位子都是用這個比較多。
但這個 translate 還有另一個妙用,假設我今天想讓 box1 在畫面的正中央
.box1 {
position: absolute;
width: 150px;
height: 150px;
background: red;
top: 50%;
left: 50%;
}
此時這個 box1 的左上角會在畫面的正中央,那要怎麼讓他的中心的對到畫面正中央呢
利用 transform。
.box1 {
position: absolute;
width: 150px;
height: 150px;
background: red;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
這裡的 50% 是指 box1 寬&高的 50%,所以 box1 就會被移到想要的位置上了
盒模型 box model
盒模型 box model 是 CSS 中很重要的東西。
必須了解 width, height, padding, border, margin 對於 box 大小的關係
預設情況下是 box-sizing: content-box;
也就是固定 content 的寬高,再加上 padding & border
那有沒有辦法 border 固定寬高呢?
用 box-sizing: border-box;
Display
除此之外也要知道 display 的三種形式 block
, inline
, inline-block
block
第一個是 block
,block 你要調什麼都可以(border, padding 等等)
代表元素有 div
, h1
, p
inline
再來是 inline
,調 width, height 都沒用,是根據內容去顯示。
調 margin 只有左右會動,上下不會
調 padding 左右會動,調上下只有背景會動,但不影響元素位置
代表元素是 span
, a
inline-block
最後是 inline-block
對外像 inline
一樣可以併排,對內像 block
可調各屬性,與 block 的差別就在能否並排而已。
代表元素是 button
, input
, select
inline-block 之間可能會有間隙的原因是因為你程式碼有空格(換行),可以用註解填補:
Inline-Block元素多出來的間隙
其實除了上面這些之外,還有像是 float
, flex box
, grid
等排版。
在使用時機上各有其強項,例如:
若要做出文繞圖,或是要支援 IE11以下的,會使用 float
flex
較適合單一元件下單一排版時
grid
較適合在 HTML 結構有巨大變化,還有二維排版
以下用來熟悉這些 display 的小遊戲:
flex
flexbox froggy
flexbox pirate
flexbox 介紹
grid
grid garden
grid 介紹
position
最後要說到定位 position
預設是 static
,會照順序排列下去
如果更動它的位置,會牽一髮動全身。
那如果 position: relative;
調整他的位置時,並不會影響到其他元素的位置。
position: fixed;
則是針對 viewport(瀏覽器你看得到地方)去做定位。
position: absolute;
針對某個參考點進行定位
那什麼可以當作參考點?就是往上找,第一個不是
static
的點
所以通常我們會想將要移動的元素 position 設為absolute
基準點的 position 設為relative
*這邊要注意的是,設為absolute
的東西,會脫離原本的坐標系,由下一個元素遞補上來
其實 position 還有一個很新的,叫做 position: sticky;
.box {
background: red;
top: 10px;
position: sticky;
z-index: 2;
}
這個意思就是當你網頁往下滑,這個 box 此時處於 static
,但當我們把網頁往下滑,他被移動到 viewport 距離 top 10px 時,你就可以把它想成 fixed
,他會被定在那個位置。
z-index
再來說 z-index
,其實就是階層,z-index
越大越前面,如 z-index: 1;
,規則是先比 z-index,相同時再比先後順序。
在排版之前問自己幾個問題
- 元素是絕對定位還是相對定位?
- 元素相對於哪裡排版?
- 元素與相鄰元素相對關係?
- 元素內部怎麼排?
RWD, Response Web Design
RWD 的全名是 Response web design
使用時要在 head 加上這行
<meta name="viewport" content="width=device-width, initial-scale=1.0">
content="width=device-width
就是將顯示的寬度變成裝置寬度
initial-scale=1.0
則是縮放比例為一倍,將內容都等比例縮放
除了這兩個之外,其實還有其他屬性可用
例如像是 maximum-scale
, user-scalable
等等
maximum-scale = 2
表示使用者最多可以放大兩倍去觀看
media query
接著要講 CSS media query
先看一段 code
.title{
color: red;
}
@media(max-width:768px){
.title{
color: green;
}
.content{
font-size: 30px;
}
}
@media(max-width:375px){
.title{
color: blue;
}
}
一般來說我們寫 CSS 都是最上面的那種寫法,但設計 RWD 時,我們會使用 @media
,他可以在你達成指定的條件時,觸發此 CSS 語法。
所以當我們縮小寬度至 768px 時,顏色會變成綠色,字大小也會變成 30px;寬度持續縮到 375px 時,顏色會再變成藍色。
看起來好像滿容易的,但要注意一點,如果手機轉成橫向呢?
寬是會變的喔,所以就會 >375px,而變成綠色的了,這個部分在設計時也要特別注意!
另外,在寫程式碼時我們總不可能手動將瀏覽器縮成各種 size 吧。
在 devtool 裡就有內建可以模擬各種 size 的工具
左上角 toggle device toolbar > 可以選擇 device 或是自訂長寬
滑鼠移到螢幕上也會出現手指大小的圓圈,可以模擬使用者的手指,這樣在開發上會更加方便。
\
以往我們在寫寬度時會用 width,這樣寫用電腦看沒事,但在寬度比較小的載具上時,就會出現會需要左右滑動的狀態了。
其實這樣是一個十分不好的使用者體驗
這時可以用 max-width
在高解析度的畫面他跟 width 的功能一樣,但縮小 width 時,他就會自適應變窄,也就可以避免 x軸的 bar 出現了。
.wrap{
max-width: 600px;
margin: 0 auto;
display: flex;
}
.menu{
width: 30%;
}
.content{
width: 70%;
}
所以我們可以在最外層使用 max-width
,內層使用 percent 讓版面自適應。