CSS的编码技巧
CSS的N個編碼技巧
垂直居中
如何將一個未知高度的元素垂直居中,通常有兩種常用的方法:
1、用絕對定位和translate
//html <div class="parent"><div class="child">center</div> </div>//css .parent{height: 300px;width: 300px;position: relative;background-color: bisque; } .child{position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);padding: 30px;background-color: cornflowerblue; }2、基于 Flexbox 的解決方案
這是毋庸置疑的最佳解決方案,因為 Flexbox是專門針對這類需求所設(shè)計的,只是一些老的瀏覽器版本兼容性可能不是很好,具體可以查看caniuse,現(xiàn)代瀏覽器一般沒問題。
.parent{height: 300px;width: 300px;background-color: bisque;display: flex;justify-content: center;align-items: center; } .child{padding: 30px;background-color: cornflowerblue; }緊貼底部的頁腳
<body><main>hello</main><footer></footer> </body>在網(wǎng)站中,不管頁面長度如何,我們都期望頁腳應(yīng)該緊貼底部。在頁面夠長時,顯示沒有問題,當頁面較短時,頁腳就會跑上去。
一個直觀的方法,就是可以用calc計算出main的最小高度:min-height:calc(100vh - footer的高度);,這樣做的前提就是已知footer的高度,如果footer的高度也是有它其中的內(nèi)容決定,這樣就行不通了。
解決這個問題依然可以用Flexbox。首先我們需要對body元素設(shè)置 display:flex,因為它是這兩個主要區(qū)塊的父元素,當父元素獲得這個屬性之后,就可以對其子元素觸發(fā)“伸縮盒布局模型”。我們還需要設(shè)置flex-direction:column,把伸縮方向設(shè)為豎直方向。然后,給main的flex屬性指定一個大于 0 的值(比如1)。
這樣,不管main和footer的內(nèi)容多少,footer都會緊貼頁面底部。
小提示
九宮格圖片展示
朋友圈、微博的圖片展示會根據(jù)數(shù)量不同而樣式不同,這也可以用純css實現(xiàn)。在《css揭秘》中,根據(jù)兄弟元素的數(shù)量來設(shè)置樣式講到的技巧就可以解決這個問題。
我們知道css中有一些跟子元素排序相關(guān)的偽類選擇器,例如,
這些選擇器單用很容易理解,其實,可以把它們聯(lián)合起來,用以更精確定位元素。
在下面這個例子中,img:nth-child(2):nth-last-child(3)表示定位正向數(shù)排第二、倒向數(shù)排第三的img元素,也就是,只有總數(shù)為4,且正向排第二的元素滿足條件。將這個元素的margin-right調(diào)大,就能將4張圖情況下第三張圖 “擠” 到下一排,實現(xiàn)四張圖的四方格排列。img:only-child表示只有一張圖的情況,這個時候要按照圖片的橫豎比例顯示,因此圖片不能設(shè)置height和width,而是用max-height max-width限制圖片的高/寬最大值。
<p>天氣真好!</p> <div class="album"><img src="./images/bg.jpg" /><img src="./images/cat2.jpg" /><img src="./images/pic1.jpg" /><img src="./images/pic2.jpg" /><img src="./images/pic3.jpg" /><img src="./images/pic4.jpg" /><img src="./images/pic5.jpg" /><img src="./images/pic6.jpg" /><img src="./images/pic9.jpg" /> </div> .album{margin-left: 50px;width: 342px; } img{height: 110px;width: 110px; } img:only-child{height: initial; /*相當于刪除已設(shè)置的某一屬性*/width: initial;max-width: 230px;max-height: 230px; } img:nth-child(2):nth-last-child(3){margin-right: 110px; }靈活的背景定位
假如寫了一封信,要在結(jié)尾處蓋一個標記。我們可以將這個標記作為背景圖定位到右下角。
background-position屬性用于設(shè)置背景圖像在元素中的位置。我們設(shè)置background-position: right bottom,標記會緊貼右下角。
要使標記與邊框有一定距離,可以設(shè)置background-position: right 20px bottom 20px。
如果想要使背景距離邊框的距離剛好和padding相同(即使修改padding的值也如此),也可以修改background-origin。每個元素對應(yīng)三個矩形框:border box(邊框的外沿框)、padding box(內(nèi)邊距的外沿框)和 content box(內(nèi)容區(qū)的外沿框),當我們寫background-position: right bottom時,默認的是padding box的右下角。如果要對齊content box的右下角,就可以修改background-origin:content-box;
background-position的另一個常見應(yīng)用就是雪碧圖。當一個網(wǎng)頁中用到很多小圖標,我們可以將這些小圖標合成一張圖,以減少網(wǎng)絡(luò)請求。使用的時候就通過background-position定位不同的圖標。
比如這樣一張雪碧圖,已知每個圖標的尺寸是200px,圖標與圖標的間隔是20px。
雪碧圖的background-position是負數(shù),相當于把背景圖片相對于元素左上角往上挪或往左挪一定距離,比如把背景圖往左挪220px,此時元素左上角就對著櫻桃的左上角,顯示的背景圖就是櫻桃。
條紋背景
條紋背景是基于漸變背景。
<div class="bg"></div> .bg{height: 100px;width: 200px;background: linear-gradient(#fb3,#58a); }
將這兩個色標拉近:
div頂部的 20% 區(qū)域被填充為 #fb3 實色,而底部 20% 區(qū)域被填充為 #58a 實色。真正的漸變只出現(xiàn)在容器 60% 的高度區(qū)域。
如果兩個顏色都設(shè)為50%,就得到了兩塊均分div背景地實色。
因為漸變是一種由代碼生成的圖像,我們能像對待其他任何背景圖像那樣對待它,而且還可以通過 background-size 來調(diào)整其尺寸。
由于背景在默認情況下是重復(fù)平鋪的,整個容器其實已經(jīng)被填滿了水平條紋。
也可以創(chuàng)建不等寬條紋:
我們可以將上面地代碼改成:
background: linear-gradient(#fb3 30%,#58a 0);如果要創(chuàng)建多色條紋:
background:linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);螞蟻行軍邊框
<div class="ants-border">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Laudantium, debitis vel quam tempora ut nisi voluptatibus rem ab. Quas, cum. Itaque, dignissimos! Quos, eos placeat eveniet quasi amet eius officiis! </div> .ants-border{width: 500px;padding: 1em;border: 1px solid transparent;background-image: linear-gradient(white, white), repeating-linear-gradient(-45deg,#000 0%, #000 25%,#fff 0%, #fff 50%);background-size: 10px 10px;background-clip: padding-box, border-box;animation: ants 10s linear infinite; } @keyframes ants {to {background-position: 100%;} }繪制步驟:
1、給div加一層黑白色條紋背景。
.ants-border{width: 500px;background-image: repeating-linear-gradient(-45deg, #000 0%, #000 25%, #fff 0%, #fff 50%); background-size: 10px 10px; /*控制條紋的寬度*//*默認背景圖像會repeat鋪滿全屏*/ }
2、再加一層白色背景。當一個元素設(shè)置多個background-image時,如果位置重疊,則寫在前面的背景會覆蓋寫在后面的背景。此時背景為白色。
3、背景有一個屬性background-clip,初始值是border-box,意味著背景會鋪滿border-box。
為了讓條紋背景露出來形成螞蟻邊框,我們將兩層背景的background-clip分別設(shè)為padding-box和border-box。
此時白色背景鋪滿padding-box,條紋背景鋪滿border-box,此時依然時白色背景,因為沒有設(shè)置border時,這兩個box的范圍是重疊的。所以設(shè)置一個1px的border,顏色為透明色。
.ants-border{...border: 1px solid transparent; }
4、通過動畫不斷改變背景的位置,形成移動的“螞蟻”
裁切路徑(clip-path)
clip-path允許我們把元素裁剪為我們想要的任何形狀。
<img class="pic" src="images/pic7.jpg">菱形:
.pic{clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%); }圓形:
.pic{clip-path: circle(50%); }也可以指定svg作為剪切路徑:
<img class="pic" src="images/pic7.jpg"> <svg><clipPath id="myPath" clipPathUnits="objectBoundingBox"><path d="M0.5,1C 0.5,1,0,0.7,0,0.3A 0.25,0.25,1,1,1,0.5,0.3A 0.25,0.25,1,1,1,1,0.3C 1,0.7,0.5,1,0.5,1 Z" /></clipPath> </svg> .pic{clip-path: url(#myPath) }
CSS 裁切路徑可以同時使用百分比數(shù)值(它會以元素自身的寬高作為基數(shù)度進行換算)和絕對長度值。
偽類
借助偽類,可以用清晰的html結(jié)構(gòu)巧妙地實現(xiàn)很多效果。
平行四邊形背景
將長方形變成平行四邊形,可以用transform: skewX(degree),直接用于元素上的話,文字也會變形。對此,可以把所有樣式應(yīng)用到偽元素上,然后再對偽元素進行變形。因為我們的內(nèi)容并不是包含在偽元素里的,所以內(nèi)容并不會受到變形的影響。這適用于其他任何變形樣式,當我們想變形一個元素而不想變形它的內(nèi)容時就可以用到它。
對話氣泡
<div class="dialogue">你說了啥?</div> .dialogue{margin-top: 50px;padding: 10px;border-radius: 2px;;display: inline-block;position: relative;border: 1px solid #ccc;max-width: 300px;background-color: #fff; } .dialogue:before{content: '';height: 8px;width: 8px;border: 1px solid;border-color: #ccc transparent transparent #ccc;background-color: #fff;position: absolute;top: 15px;right: -6px;transform: rotate(135deg); }擴大可點擊區(qū)域
對于那些較小的、難以瞄準的控件來說,如果不能把它的視覺尺寸直接放大,將其可點擊區(qū)域向外擴張往往也可以提升用戶體驗。
偽元素可以代表其宿主元素來響應(yīng)鼠標交互,所以我們可以在按鈕的上層覆蓋一層透明的偽元素,并讓偽元素在四個方向上都比宿主元素大出10px。
button {position:relative;/* [其余樣式] */ } button:before {content:'';position:absolute;top:-10px; right:-10px;bottom:-10px; left:-10px; }基于偽元素,我們基本上可以把可點擊區(qū)域設(shè)置為任何想要的尺寸、位置或形狀,甚至可以脫離元素原有的位置。
自定義的復(fù)選框
自定義的復(fù)選框
在表單元素中,為了擴大checkbox的點擊范圍,我們經(jīng)常用label和checkbox對應(yīng),這里可以把樣式加在label上,隱藏checkbox。
<input class="switch" type="checkbox" id="connect" /> <label for="connect"></label> .switch{ /*隱藏復(fù)選框,通過label來響應(yīng)點擊*/position: absolute; /*不能使用 display:none,那樣會把它從鍵盤tab鍵切換焦點的隊列中刪除*/clip: rect(0,0,0,0) } .switch + label { /*設(shè)置未選中狀態(tài)的label樣式*/display: inline-block;height: 15px;width: 30px;border-radius: 10px;background-color: #eee;position: relative; } .switch + label:before { /*可滑動的小按鈕為label:before偽類*/content: '';display: inline-block;position: absolute;height: 15px;width: 15px;border-radius: 50%;background-color: #fff;right: 0;top: 0;box-shadow: 0 0 2px #666; } .switch:checked + label { /*設(shè)置選中狀態(tài)的label樣式*/background-color: yellowgreen; } .switch:checked + label:before {left: 0; }和:checked類似,還可以利用偽類選擇器:hover,:focus,:disabled設(shè)置復(fù)選框不同狀態(tài)的樣式。
毛玻璃效果
毛玻璃效果就是模糊效果,關(guān)鍵是讓誰模糊?對元素運用filter: blur(30px)會讓它的子元素也變模糊,所以不能讓class="content"元素模糊;這里文本所在的區(qū)域?qū)捀呤遣欢ǖ?#xff0c;所以沒辦法用一個空div做模糊效果,然后“墊”在class="content"元素下面。于是,我們想到了偽類。
將偽類的位置設(shè)置成和內(nèi)容元素一樣,使用負的 z-index 來把一個偽類移動到class="content"元素下層。在使用負的 z-index 來把一個子元素移動到它的父元素下層時,請務(wù)必小心:如果父元素的上級元素有背景,則該子元素將出現(xiàn)在它們之后。 所以為class="content"元素設(shè)置z-index: 1;使偽元素出現(xiàn)在父父元素(class="poem"元素)之上。
為偽元素設(shè)置和class="poem"元素一樣的背景,為了讓偽元素和class="poem"元素的背景重疊,用background-attachment: fixed 。此時對偽元素使用filter: blur(30px);就形成了毛玻璃效果。
.poem{width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: center; } .poem,.content::before{background: url('./images/pic9.jpg');background-size: cover;background-attachment: fixed; } .poem .content{box-sizing: border-box;color:#f9f9f9;font-size: 20px;line-height: 2.2em;letter-spacing: 3px;text-align: center;padding: 40px 30px 35px 40px;background: hsla(0, 0%, 100%, 0.3);position: relative;overflow: hidden;z-index: 1; } .poem .content::before{content: '';position: absolute;top: 0;left: 0;right: 0;bottom: 0;filter: blur(30px);margin: -30px;z-index: -1; }css濾鏡(filter)
filter mdn
hsl
學(xué)習(xí)css濾鏡還是要先學(xué)習(xí)一下hsl色彩模型,可以看這位小姐姐的視頻,色彩系列課程 講得很清楚。
色相(HUE): 色彩的一種屬性,光學(xué)透色以波長來劃分。色相是不含黑白灰的純色,下面是一個純色的基礎(chǔ)色輪。
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1bcac758e7a44acab29e17f9886b4eea~tplv-k3u1fbpfcp-watermark.image
飽和度(SATURATION):又稱純度,所顯示色彩的鮮艷深淺。
明度(LIGHTNESS):色彩的亮度,高低決定明暗。
在色相的基礎(chǔ)上,調(diào)整飽和度和明暗度可以得到不同的色彩效果。
不規(guī)則形狀投影
box-shadow沒有辦法給不規(guī)則形狀加陰影。比如氣泡對話框。
使用filter:drop-shadow可以解決這個問題。
雖然都是處理陰影,box-shadow 是給整個元素box加陰影,而 drop-shadow 只給不透明的部分加陰影。以圖片為例,下圖除了水果部分,周圍都是透明的。
染色效果
img{height: 100px;width: 100px;border-radius: 50%;filter: sepia() hue-rotate(70deg);transition: .5s filter; } img:hover{filter: none; }通過模糊來弱化背景
模糊背景的應(yīng)用場景還挺多的,比如手機解鎖、網(wǎng)站登錄、qq音樂播放頁面模糊專輯圖片來當背景。
簡易音樂播放面板
<div class="main"><img src="./images/reading.webp" /><div>東區(qū)的咖啡座<br>時間的杯子<br>滿滿的心事<br>blablabla~~~~<br></div> </div> .main{position: relative;display: flex;flex-direction: column;align-items: center;color: #fff;text-align: center;font-size: 20px;line-height: 2em;background: rgba(0, 0, 0, 0.1); } .main:before{z-index: -1;content: '';position: absolute;top: 0;left: 0;bottom: 0;right: 0;background: url("./images/reading.webp");background-size: 100% 100%;filter: blur(30px) opacity(0.6); /*這里不能將濾鏡直接加在.main元素,而是將背景和濾鏡都加在偽類上。因為,父元素加了濾鏡,它的子元素都會一起由該濾鏡改變。*/ } .main img{height: 160px;width: 160px;border-radius: 50%;margin: 100px 0 50px;animation:rotate 5s linear infinite; }@keyframes rotate {to{transform: rotate(1turn);} }交互式的圖片對比控件
<div class="image-slider"><img class="gray" src="./images/cat1.jpg"/><div class="upper-img"><img src="./images/cat1.jpg"/> <!--比對的兩張圖可以是任意兩張圖,只是這里是濾鏡對比--></div><input type="range" /> </div> .image-slider {position: relative;display: inline-block; } .image-slider > div {position:absolute;top: 0;left: 0;right: 0;bottom: 0;width: 50%;overflow: hidden; } .image-slider img {display: inline-block;user-select: none; } .image-slider .gray {filter: sepia(); } .image-slider input[type="range"]{position: absolute;left: 0;bottom: 10px;width: 100%;margin: 0;filter: contrast(0.5);mix-blend-mode: luminosity; } <script>let range = document.querySelector('input[type="range"]'),upperImg = document.querySelector('.upper-img')range.addEventListener('input', function(ev){upperImg.style.width = ev.target.value + '%'}) </script>文字描邊和文字發(fā)光
text-shadow 屬性向文本添加一個或多個陰影。
動畫
緩動、逐幀 – animation-timing-function
我們經(jīng)常會用到動畫animation, 比如animation:rotate 5s linear infinite, 這里第三個參數(shù)linear是動畫時間函數(shù)animation-timing-function, 它定義CSS動畫在每一動畫周期中執(zhí)行的節(jié)奏,通俗一點,就是動畫速度,比如常見的,勻速(linear)、先快后慢(ease-out)、先慢后快(ease-in)、中間快兩頭慢(ease-in-out),這些都是方便的寫法,但是不夠定制,比如,我們想要一個動畫,前面特別快,10%的時間完成90%的動畫,僅用這些關(guān)鍵詞就做不到。
為了讓動畫速度更加DIY,可以用cubic-bezier, 它也是animation-timing-function的一種,animation: rotate 1.5s cubic-bezier(.27,1.07,.75,.96) infinite;。 cubic-bezier稱為三次貝塞爾曲線,主要是生成速度曲線的函數(shù)。 它的推導(dǎo)和計算后面會單獨一篇講,我們這里主要看它的使用。cubic-bezier(.27,1.07,.75,.96)參數(shù)接受四個值,這四個值其實是兩個控制點(下圖中,紅色和綠色的手柄)的坐標。
通過調(diào)整這兩個控制點,可以調(diào)整黑色貝塞爾曲線的斜率,這個斜率就代表了速度,上圖的貝塞爾曲線的斜率先大后小,再變大,對應(yīng)的動畫速度也是先快后慢再快。
調(diào)整貝塞爾曲線的網(wǎng)站,cubic-bezier.com/#.17,.67,.8….
這個貝塞爾時間函數(shù)對應(yīng)的動畫速度就是先快后慢,我們用它來寫一個轉(zhuǎn)圈的加載動畫。
第一個是cubic-bezier(.23,1.21,.81,.94); 第二個是linear; 第三個是steps(n)。
動畫除了上面討論的平滑過渡,還有就是逐幀過渡steps(n)。與平滑過渡迥然不同的是,steps(n)會根據(jù)你指定的步進數(shù)量(n),把整個動畫切分為n幀,而且整個動畫會在幀與幀之間硬切,不會做任何插值處理。
逐幀動畫結(jié)合雪碧圖是實現(xiàn)圖片素材動畫的基礎(chǔ)。比如我們可以用三張圖代表小鳥飛翔時翅膀的三種狀態(tài),再通過逐幀動畫不斷切換這三張圖,就可以實現(xiàn)小鳥的飛。
可暫停的動畫 – animation-play-state
假如要實現(xiàn)這樣一個效果:展示一幅很長的圖,當鼠標停在圖上,圖開始移動,鼠標移開,圖停止移動,鼠標再移上去,圖從上次停的地方又開始移動。
動畫延遲 – animation-delay
animation-delay規(guī)定在動畫開始之前的延遲。
有些時候可以用這種 頭像+水波紋 的效果提示新消息,這可以用animation-delay實現(xiàn):
<div class="wave"><img src="./images/cat1.jpg" /><span></span><span></span> </div> .wave{ position: relative; } .wave img{height: 50px;width: 50px;border-radius: 50%; } .wave span{position: absolute;z-index: -1;top: -1px;left: -1px;height: 50px;width: 50px;border-radius: 50%;border: 1px solid orange;animation: 2s wave linear 4;opacity: 0; } .wave span:nth-of-type(2){animation-delay: 1s; /*用animation-delay將兩個span的動畫錯開,形成水波紋*/ } @keyframes wave {50%{transform: scale(1.2);opacity: 1; }100%{transform: scale(1.4);opacity: 0;} }總結(jié)
- 上一篇: 22个超详细的 JS 数组方法
- 下一篇: CSS3运算 calc()函数是怎么实现