css 揭祕
[希]Lea verou 著
css 魔法 譯css
該書涵蓋7大主題,47個css技巧,是css進階必備書籍,開闊思路,探尋更優雅的解決方案。這本書徹底用css渲染出的html寫成的(佈局、圖片、顏色、頁碼、章節號等)。html
瀏覽器前綴書寫:應該把標準語法排在最後,經過層疊機制確保哪條聲明最終生效。css3
background: rgb(255, 128, 0); /* 回退機制 */ background: -moz-linear-gradient(90deg, yellow, red); /* 火狐 */ background: -o-linear-gradient(90deg, yellow, red); /* Opera */ background: -webkit-linear-gradient(90deg, yellow, red); /* Safari、Chrome*/ background: linear-gradient(0deg, yellow, red);tip: 瀏覽器前綴生成工具:
使用Modernizr工具給根元素()添加輔助類,好比 textshadow
或 no-textshadow
,針對支持或不支持某些特性的瀏覽器來分別編寫樣式git
h1 { color: gray; } .textshadow h1 { color: transparent; text-shadow: 0 0 .3em gray; }
嘗試的 css 特性很是新,能夠試試 @supports 規則實現回退,將其視做瀏覽器「原生」的 Modernizr。github
h1 { color: gray; } @supports (text-shadow: 0 0 .3em gray) { h1 { color: transparent; text-shadow: 0 0 .3em gray; } }
tip: 慎用 @supports, 存在兼容性web
js 實現:作一些特性檢測而後給根元素加一些輔助類。若是要檢測某個樣式屬性是否被支持,核心思路就是在任一元素的 element.style 對象上檢查該屬性是否存在。算法
var root = document.documentElement; // <html> if ('textShadow' in root.style) { root.classList.add('textshadow'); } else { root.classList.add('no-textshadow'); } // 多個 function testProperty (property) { var root = document.documentElement; // <html> if (property in root.style) { root.classList.add(property.toLowerCase()); return true; } root.classList.add('no-' + property.toLowerCase()); return false; }
檢查某個具體的屬性值是否支持,須要把它賦給對應的屬性,而後再檢查瀏覽器是否還保存着這個值。數據庫
var dummy = document.createElement('p'); dummy.style.backgroundImage = 'linear-gradient(red, tan)'; if (dummy.style.backgroundImage) { root.classList.add('lineargradients'); } else { root.classList.add('no-lineargradients'); } // 多個 function testValue(id, value, property) { var dummy = document.createElement('p'); dummy.style[property] = value; if (dummy.style[property]) { root.classList.add(id); return true; } root.classList.add('no-' + id); return false; }
標準的每項規範從最初啓動到最終成熟,必經階段:瀏覽器
關於css三、css4及其餘傳說微信
tip:爲何不會有CSS4了?
舉例:
font-size: 20px; line-height: 1.5; // 等同於 line-height: 30px;
button { padding: .3em .8em; border: 1px solid rgba(0, 0, 0, .1); background: #58a linear-gradient(hsla(0, 0%, 100%, .2), transparent); border-radius: .2em; box-shadow: 0 .05em .25em rgba(0, 0, 0, .5); color: white; text-shadow: 0 -.05em .05em rgba(0, 0, 0, .5); font-size: 125%; line-height: 1.5; } button.cancel { background-color: #c00; } button.ok { background-color: #6b0; }
border-width: 10px; border-left-width: 0;
// 舉例,在建立提示框的時候,小箭頭可以自動繼承背景和邊框的樣式 .callout { position: relative; } .callout::before { content: ''; position: absolute; top: -.4em; left: 1em; padding: .35em; background: inherit; border: inherit; border-right: 0; border-bottom: 0; transform: rotate(45deg); }
ul {--accent-color: purple;} ol {--accent-color: rebeccapurple;} li {background: var(--accent-color);}
border: 10px solid hsla(0, 0%, 100%, .5); background: white; background-clip: padding-box;
box-shadow 方案
background: yellowgreen; box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink, 0 2px 5px 15px rgba(0, 0, 0, .6);
注意事項:不影響佈局,不受 box-sizing 屬性影響,outset的區域不響應鼠標事件,改成inset。
outline 方案
background: #655; outline: 1px dashed #fff; outline-offset: -10px;
不貼合border-radius
background-position 方案
background: url(http://csssecrets.io/images/code-pirate.svg) no-repeat bottom right #58a; background-position: right 20px bottom 10px;
background-origin 方案
background: url(http://csssecrets.io/images/code-pirate.svg) no-repeat bottom right #58a; background-origin: content-box;
background-position是以padding box爲準的
calc() 方案
background: url(http://csssecrets.io/images/code-pirate.svg) no-repeat bottom right #58a; background-position: calc(100% - 20px) calc(100% - 10px);
background: tan; border-radius: .8em; padding: 1em; box-shadow: 0 0 0 .6em #655; outline: .6em solid #655;
勾股定理:a*a + b*b = c*c
擴張半徑須要比描邊的寬度值小,但同時要比 (Math.sqrt(2) - 1) * r
(根號2 - 1)r 大,r表示border-radius
橫向
background: linear-gradient(#fb3 50%, #58a 0); background-size: 100% 30px;
垂直條紋
background: linear-gradient(to right, #fb3 50%, #58a 0); background-size: 30px 100%;
斜向條紋
background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0); background-size: 42.4px 42.4px;
靈活的同色繫條紋
background: #58a; background-image: repeating-linear-gradient(30deg, hsla(0,0%,100%,.1), hsla(0,0%,100%,.1) 15px, transparent 0, transparent 30px);
網格
background: #58a; background-image: linear-gradient(white 2px, transparent 0), linear-gradient(90deg, white 2px, transparent 0), linear-gradient(hsla(0,0%,100%,.3) 1px, transparent 0), linear-gradient(90deg, hsla(0,0%,100%,.3) 1px, transparent 0); background-size: 50px 50px, 50px 50px, 10px 10px, 10px 10px;
波點: 兩層,第二層背景偏移定位置必須是貼片寬高的一半
background: #655; background-image: radial-gradient(tan 20%, transparent 0), radial-gradient(tan 20%, transparent 0); background-size: 30px 30px; background-position: 0 0, 15px 15px;
scss mixin
// scss mixin @mixin polka($size, $dot, $base, $accent) { background: $base; background-image: radial-gradient($accent $dot, transparent 0), radial-gradient($accent $dot, transparent 0); background-size: $size $size; background-position: 0 0, $size/2 $size/2; } // 調用 @include polka(30px, 30%, #655, tan);
棋盤: 用兩個直角三角形來拼合出咱們想要的方塊,把第二層漸變在水平和垂直方向均移動貼片長度的一半
.checkerboard { background: #eee; background-image: linear-gradient(45deg, rgba(0,0,0,.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,.25) 0), linear-gradient(45deg, rgba(0,0,0,.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,.25) 0); background-position: 0 0, 15px 15px; background-size: 30px 30px; } // scss mixin @mixin checkerboard($size, $base, $accent: rgba(0, 0, 0, .25)) { background: $base; background-image: linear-gradient(45deg, $accent 25%, transparent 0, transparent 75%, $accent 0), linear-gradient(45deg, $accent 25%, transparent 0, transparent 75%, $accent 0); background-size: 2*$size 2*$size; background-position: 0 0, $size $size; } // 調用 @include checkerboard(15px, #58a, tan);
棋盤-svg
background: #eee url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill-opacity=".25" >\ <rect x="50" width="50" height="50" />\ <rect y="50" width="50" height="50" />\ </svg>'); background-size: 30px 30px;
棋盤-圓錐漸變實現:存在兼容性
background: repeating-conic-gradient(#bbb 0, #bbb 25%, #eee 0, #eee 50%); background-size: 30px 30px;
調色盤: 圓錐漸變
border-radius: 50%; background: conic-gradient(red, yellow, lime, aqua, blue, fuchsia, red);
技巧:背景邊框:在石雕背景圖片之上,再疊加一層純白的實色背景
padding: 1em; border: 1em solid transparent; background: linear-gradient(white, white) padding-box, url(http://csssecrets.io/images/stone-art.jpg) border-box 0 / cover; width: 21em; overflow: hidden; resize: both;
信封
padding: 1em; border: 16px solid transparent; border-image: 16 repeating-linear-gradient(-45deg, red 0, red 1em, transparent 0, transparent 2em, #58a 0, #58a 3em, transparent 0, transparent 4em);
行軍的螞蟻
.ants { padding: 1em; border: 1px solid transparent; background: linear-gradient(white, white) padding-box, repeating-linear-gradient(-45deg, black 0, black 25%, transparent 0, transparent 50%) 0 / .6em .6em; animation: ants 12s linear infinite; max-width: 20em; font: 100%/1.6 Baskerville, Palatino, serif; } @keyframes ants { to { background-position: 100% 100% } }
border-image原理:九宮格伸縮發:把圖片切割成九塊,而後把它們應用到元素邊框相應的邊和角。
原理體驗:border-image
腳註
border-top: .15em solid transparent; border-image: 100% 0 0 linear-gradient(90deg, currentColor 4em, transparent 0); padding-top: .5em;
因爲後面特別多,就不一一列舉了展現圖片了,感興趣的去看源碼及效果吧。
border-radius: 50%;
如果寬高一致,就顯示爲一個圓,寬高不等,就顯示一個橢圓。
若border-radius值爲寬高小的一邊,就表現爲小的邊爲半圓,長的邊爲直線。
可單獨制定水平和垂直半徑:用 / 分隔值便可。border-radius: 100px / 75px
border-radius: 50% / 100% 100% 0 0;
border-radius: 100% 0 0 0;
嵌套方案:外層skew變形,但內容變形了,對內容再應用一次反向的 skew() 變形,從而抵消容器的變形。
<a class="button"><div>click me</div></a> .button { transform: skewX(-45deg); } .button > div { transform: skewX(45deg); }
僞元素方案:parallelograms-pseudo
嵌套變形方案:diamond-images
<div class="pic"> <img src=""adam-catlace.jpg alt="..."/> </div> .pic { width: 400px; transform: rotate(45deg); overflow: hidden; } .pic > img { max-width: 100%; transform: rotate(-45deg) scale(1.42); }
裁切路徑方案:diamond-clip
.img { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); transition: 1s clip-path; } .img:hover { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
一個角
background: #58a; background: linear-gradient(-45deg, transparent 15px, #58a 0);
二個角
background: #58a; background: linear-gradient(-45deg, transparent 15px, #655 0) right, linear-gradient(45deg, transparent 15px, #58a 0) left; background-size: 50% 100%; background-repeat: no-repeat;
background: #58a; background: linear-gradient(135deg, transparent 15px, #58a 0) top left, linear-gradient(-135deg, transparent 15px, #58a 0) top right, linear-gradient(-45deg, transparent 15px, #58a 0) bottom right, linear-gradient(45deg, transparent 15px, #58a 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; // scss mixin @mixin beveled-corners ($bg, $tl:0, $tr:$tl, $br:$tl, $bl:$tr) { background: $bg; background: linear-gradient(135deg, transparent $tl, $bg 0) top left, linear-gradient(225deg, transparent $tr, $bg 0) top right, linear-gradient(-45deg, transparent $br, $bg 0) bottom right, linear-gradient(45deg, transparent $bl, $bg 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; } // 調用 @include beveled-corners(#58a, 15px, 5px);
弧形切角(內凹圓角):用徑向漸變替代上述線性漸變。scoop-corners
background: #58a; background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left, radial-gradient(circle at top right, transparent 15px, #58a 0) top right, radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right, radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; // scss mixin @mixin scoop-corners($bg, $tl:0, $tr:$tl, $br:&tl, $bl:$tr) { background: $bg; background: radial-gradient(circle at top left, transparent $tl, #58a 0) top left, radial-gradient(circle at top right, transparent $tr, #58a 0) top right, radial-gradient(circle at bottom right, transparent $br, #58a 0) bottom right, radial-gradient(circle at bottom left, transparent $bl, #58a 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; } // 調用 @include scoop-corners();
內聯 svg 與 border-image 方案:bevel-corners
border: 20px solid #58a; border-image: 1 url('data:image/svg+xml,\ <svg xmlns="http://www.w3.org/2000/svg"\ width="3" height="3" fill="%2358a">\ <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\ </svg>'); background: #58a; background-clip: padding-box;
裁切路徑方案:好處:可以使用任意類型的背景,好比圖片。bevel-corners-clipped
background: #58a; clip-path: polygon( 20px 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 20px), 0 20px);
利用 3D 旋轉模擬實現:trapezoid-tabs
nav > a { position: relative; display: inline-block; padding: .3em 1em 0; } nav > a::before { content: ''; /* 用僞元素來生成一個矩形 */ position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; background: #ccc; transform: perspective(.5em) rotateX(5deg); transform-origin: bottom; background-image: linear-gradient(hsla(0, 0%, 100%, .6), hsla(0, 0%, 100%, 0)); border: 1px solid rgba(0, 0, 0, .4); border-bottom: none; box-shadow: 0 .15em white inset; }
對元素使用了 3D 變形以後,其內部的變形效應是「不可逆轉」的。但 2D 變形,內部是可抵消外部的變形效應。
該方案優勢:能添加背景、邊框、圓角、投影燈,而且,只須要把 transform-origin 改爲 bottom left 或 bottom right,就能夠當即獲得左側傾斜或右側傾斜的標籤頁。
基於 transform 的解決方案:pie-animated
該方案結構最簡:只需一個元素做爲容器,其餘部分由僞元素、變形屬性和css漸變實現。
@keyframes spin { to { transform: rotate(.5turn); } } @keyframes bg { 50% { background: #655; } } .pie { width: 100px; height: 100px; border-radius: 50%; background: yellowgreen; } .pie::before { content: ''; display: block; margin-left: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transfrom-origin: left; animation: spin 3s linear infinite, bg 6s step-end infinite; }
製做多個不一樣比率的靜態餅圖:pie-static
<div class="pie">20%</div> <div class="pie">60%</div> @keyframes spin { to { transform: rotate(.5turn); } } @keyframes bg { 50% { background: #655; } } .pie { position: relative; width: 100px; line-height: 100px; // line-height 自己就能夠起到設置高度的做用 border-radius: 50%; background: yellowgreen; background-image: linear-gradient(to right, transparent 50%, #655 0); color: transparent; text-align: cener; } .pie::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transfrom-origin: left; animation: spin 3s linear infinite, bg 6s step-end infinite; animation-play-state: paused; animation-delay: inherit; } document.querySelectorAll('.pie').forEach(function (pie) { var p = parseFloat(pie.textContent); pie.style.animationDelay = '-' + p + 's'; })
動畫暫停,用負的動畫延時(animation-delay: -20s)來直接跳至動畫中的任意時間點。
.pie 元素內聯樣式,僞元素繼承 inherit
svg 解決方案:pie-svg
<svg viewBox="0 0 32 32"> <circle r="16" cx="16" cy="16" /> </svg> // css svg { width: 100px; height: 100px; transform: rotate(-90deg); background: yellowgreen; border-radius: 50%; } svg > circle { fill: yellowgreen; stroke: #655; stroke-width: 32; stroke-dasharray: 38 100; /* 可獲得比率爲38%的扇區 */ }
box-shadow: 0 5px 4px -4px black;
box-shadow 第四個長度參數,擴張半徑,排在模糊半徑參數以後,這個參數會根據你指定的值去擴大或縮小(負值)投影的尺寸。應用一個負的擴張半徑,而它的值恰好等於模糊半徑,那麼投影的尺寸就會與投影所屬元素的尺寸徹底一致。
box-shadow: 3px 3px 6px -3px black;
box-shadow: 5px 0 5px -5px black, -5px 0 5px -5px black;
filter: drop-shadow(2px 2px 10px rgba(0, 0, 0, .5));
能與點狀、虛線、半透明邊框、切角、折角等不規則的形狀貼合。
可參考文章:CSS3 filter:drop-shadow濾鏡與box-shadow區別應用
濾鏡方案:color-tint-filter
img { transition: .5s filter; filter: sepia(1) saturate(4) hue-rotate(295deg); } img:hover, img:focus { filter: none; }
sepia():給圖片增長一種降飽和度的橙黃色染色效果。幾乎全部像素的色相值會被收斂到35-40.
saturate():給每一個像素提高飽和度
hue-rotate():把每一個像素的色相以指定的度數進行偏移。
混合模式方案:color-tint
<a> <img src="tiger.jpg"/> </a> a { background: hsl(335, 100%, 50%); } a > img { mix-blend-mode: luminosity; }
當兩個元素疊加時,「混合模式」控制了上層元素的顏色與下層顏色進行混合的方式。
luminosity:會保留上層元素的 hsl 亮度信息,並從它的下層吸收色相和飽和度信息。
染色:下層放主色調,上層設置 luminosity 混合模式。
mix-blend-mode:爲整個元素設置混合模式
background-blend-mode:爲每層背景單獨制定混合模式。
body, main::before { background: url('tigger.jpg') 0 / cover fixed; } main { position: relative; backgrond: hsla(0, 0%, 100%, .3); overflow: hidden; } main::before { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; filter: blur(20px); margin: -30px; }
因爲不能直接對元素自己設置模糊效果,就對一個僞元素進行處理,而後將其定位宿主到元素的下層,它的背景將會無縫匹配 的背景。
模糊效果會削減實色像素所能覆蓋的範圍,削減的幅度正是模糊半徑的長度。所以讓僞元素相對宿主元素的尺寸向外誇大至少20px
45° 折角的解決方案:folded-corner
background: #58a; /* 回退樣式 */ background: linear-gradient(to left bottom, transparent 50%, rgba(0, 0, 0, .4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-135deg, transparent 1.5em, #58a 0);
其餘角度解決方案:
.note { positon: relative; background: #58a; background: linear(-150deg, transparent 1.5em, #58a 0); border-radius: .5em; } .note::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0, 0, 0, .2) 0, rgba(0, 0, 0, .4)) 100% no-repeat; width: 1.73em; height: 3em; transform: translateY(-1.3em) rotate(-30deg); transform-origin: bottom right; border-bottom-left-radius: inheirt; box-shadow: -.2em .2em .3em -.1em rgba(0, 0, 0, .15); } // scss mixin @mixin folded-corner($bg, $size, $angle:30deg) { positon: relative; background: $bg; background: linear($angle - 180deg, transparent $size, $bg 0); border-radius: .5em; $x: $size / sin($angle); $y: $size / cos($angle); &::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0, 0, 0, .2) 0, rgba(0, 0, 0, .4)) 100% no-repeat; width: $y; height: $x; transform: translateY($y - $x) rotate(2*$angle - 90deg); transform-origin: bottom right; border-bottom-left-radius: inheirt; box-shadow: -.2em .2em .3em -.1em rgba(0, 0, 0, .15); } } // 調用 .note { @include folded-corner(#58a, 2em, 40deg); }
text-align: justify; hyphens: auto;
兩端對齊,英文,有些單詞之間的間隔太大,損傷了可讀性。實際中,兩端對齊老是與連字符斷行相輔相成。
文本折行算法:主要是 貪婪算法 和 Knuth-Plass 算法。
貪婪算法:每次分析一行,把儘量多的單詞填充改行,當遇到第一個裝不下的單詞或音節時,就移至下一行繼續處理。
Knuth-Plass 算法:高級不少,把整段文本歸入考慮範圍,從而產生出美學上更使人愉悅的效果。但計算性能稍差。
絕大多數桌面文字處理程序採用 Knuth-Plass 算法,處於性能考慮,瀏覽器採用 貪婪算法。
<dl> <dt>Name:</dt> <dd>Lea Verou</dd> <dt>Email:</dt> <dd>Lea@verou.me</dd> <dd>Leaverou@mit.edu</dd> <dt>Location:</dt> <dd>Earth</dd> </dl>
dt,dd 塊級元素。
在每一個 dd 後面添加一個 br 換行,糟糕的結構。使用生成性內容來添加換行,並以此取代br。
有一個 Unicode 字符專門表明換行:0x000A,在 css 中這個字符能夠寫做 "\000A",或簡化爲"\A"。
在 html 直接輸入換行符,會與響鈴的其餘空白符合並。保留空白和換行,white-space: pre
。
dt, dd { display: inline; } dd { margin: 0; font-weight: bold; } dd + dt::before { content: '\A'; white-space: pre; } dd + dd::before { content: ','; margin-left: -.2em; font-weight: normal; }
表格
tr: nth-child(even) { background: rgba(0, 0, 0, .2); }
文本:漸變背景條紋
padding: .5em; line-height: 1.5; background: beige; background: auto 3em; background-origin: content-box; background-image: linear-gradient(rgba(0, 0, 0, .2) 50%, transparent 0);
background-size 設置爲 line-height 的兩倍,每一個背景貼片須要覆蓋兩行代碼。
使用 pre 和 code 顯示代碼,tab 縮進代碼,瀏覽器會把其寬度顯示爲 8 個字符。
pre { tab-size: 2; }
大多數襯線字體中的 f 和 i ,i 的圓點每每會與 f 的升部發生衝突,致使二者顯示不清。爲了緩解這種狀況,出現連字。設計成 雙字形或三字形的單一組合體。
font-variant-ligatures:common-ligatures discretionary-ligatures historical-ligatures;
開啓通用連字,關閉酌情連字
font-variant-ligatures: common-ligatures no-discretionary-ligatures no-historical-ligatures;
華麗的 & 符號:ampersands
自定義下劃線:
background: linear-gradient(gray, gray) no-repeat; background-size: 100% 1px; background-origin: 0 1.15em; text-shadow: .05em 0 white, -.05em 0 white;
凸版印刷效果:letterpress
background: hsl(210, 13%, 40%); color: hsl(210, 13%, 75%); text-shadow: 0 -1px 1px black;
原理:出如今底部的淺色投影或出如今頂部的暗色投影,會讓人產生物體時凹進平面內的錯覺;同理,出如今底部的暗色投影或出如今頂部的淺色投影,會讓人產生物體從平面上凸起的錯覺。
造成錯覺的緣由:現實世界中光源老是懸在頭頂。
空心字效果:stroked-text
background: deeppink; color: white; text-shadow: 1px 1px black, -1px -1px black, 1px -1px black, -1px 1px black;
文字外發光效果:glow
a { background: #203; color: white; transition: 1s; } a:hover { color: transparent; text-shadow: 0 0 .1em white, 0 0 .3em white; } // 或 a:hover { filter: blur(.1em); }
文字凸起效果:extruded
background: #58a; color: white; text-shadow: 0 1px hsl(0, 0%, 85%), 0 2px hsl(0, 0%, 80%), 0 3px hsl(0, 0%, 75%), 0 4px hsl(0, 0%, 70%), 0 5px hsl(0, 0%, 65%), 0 5px 10px black; // scss mixin @mixin text-3d($color:white, $depth: 5) { $shadows: (); $shadow-color: $color; @for $i from 1 through $depth { $shadow-color: darken($shadow-color, 10%); $shadow: append($shadows, 0 ($i * 1px) $shadow-color, comma); } color: $color; text-shadow: append($shadows, 0 ($depth * 1px) 10px black, comma); } h1 { @include text-3d(#eee, 4)};
環形文字-svg:circular-text
cursor: not-allowed; // 禁用
border: 10px solid transparent; box-shadow: 0 0 0 1px rgba(0, 0, 0. .3) inset; background-clip: padding-box;
僞元素實現:僞元素能夠表明其宿主元素來響應鼠標交互。hit-area
button { position: relative; } button::before { content: ''; position: absolute; top: -10px; right: -10px; bottom: -10px; left: -10px; }
:checked,改僞類只在複選框被勾選時才匹配,不論這個勾選狀態是由用戶交互觸發,仍是腳本觸發。
藉助組合選擇符來給其餘元素設置樣式。當 label 元素與複選框關聯以後,也能夠起到觸發開關的做用。
<input type="checkbox" id="awesome"/> <label for="awesome">Awesome</label> input[type="checkbox"] + label::before { content: '\a0'; /* 不換行空格 */ display: inline-block; vertical-align: .2em; width .8em; height: .8em; margin-right: .2em; border-radius: .2em; background: silver; text-indent: .15em; line-height: .65; } input[type="checkbox"]:checked + label::before { content: '\2713'; background: yellowgreen; } // 不損失可訪問性的方式隱藏,不能使用display:none,會把它從鍵盤tab鍵切換焦點的隊列中徹底刪除 input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); } input[type="checkbox"]:focus + label::before { box-shadow: 0 0 .1em .1em #58a; } input[type="checkbox"]:disabled + label::before { background: gray; box-shadow: none; color: #555; }
<p>Some text [...]</p> <figure> <img src="adamcatlace.jpg" /> <figcaption> The great Sir Adam Catlace was named after Countess Ada Lovelace, the first programmer. </figcaption> </figure> <p>More text [...]</p>
但願這個 figure 元素能跟 它所包含的圖片同樣框,並且水平居中。
figure { max-width: 300px; /* 回退 */ max-width: min-content; margin: auto; } figure > img { max-width: inherit; }
min-content: 解析爲這個容器內部最大的不可斷行元素的寬度(即最寬的單詞、圖片或具備固定寬度的盒元素)
table { table-layout: fixed; width: 100%; }
經過兄弟元素的總數設置樣式
li:only-child { /* 只有一個列表項是的樣式 */ }
li:first-child:nth-last-child(1) { /* 至關於li:only-child,第一項同時是最後一項 */ }
li:first-child:nth-last-child(4) { /* 這個元素是父元素的第一個子元素,同時是從後往前數的第四個子元素,即命中一個正好有四個列表項的第一個列表項 */ }
li:first-child:nth-last-child(4), li:first-child:nth-last-child(4) ~ li { /* 當列表正好是四項時,命中全部列表項 */ }
根據兄弟元素的數量範圍來匹配元素
li:nth-child(n+b) { /* n+b, n從0開始,選中從b個元素開始的全部子元素*/ }
li:nth-child(n+4) { /* 選中除了第一、第二、第3個子元素以外的全部子元素 */ }
li:first-child:nth-last-child(n+4), li:first-child:nth-last-child(n+4) ~ li { /* 當列表至少包含四項時,命中全部列表項 */ }
-n+b:能夠選中開頭的b個元素,當列表中有4個或更少的列表項時:
li:first-child:nth-last-child(-n+4), li:first-child:nth-last-child(-n+4) ~ li { /* 當列表最多包含四項時,命中全部列表項 */ }
li:first-child:nth-last-child(n+2):nth-last-child(-n+6), li:first-child:nth-last-child(n+2):nth-last-child(-n+6) ~ li { /* 當列表包含2-6項時,命中全部列表項 */ }
實際應用篇:僞類匹配列表數目實現微信羣頭像CSS佈局的技巧
定寬內容居中,正常寫法
<footer> <div class="wrap">內容</div> </footer> footer { background: #333; } .wrap { max-width: 900px; margin: 1em auto; }
一層實現:
footer { padding: 1em; /* 回退 */ padding: 1em calc(50% - 450px); background: #333 }
絕對定位方案:
main { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
彈性盒子方案:
body { display: flex; min-height: 100vh; margin: 0; } main { /* 水平垂直居中 */ margin: auto; }
main { display: flex; align-items: center; justify-content: center; width: 18em; height: 10em; }
塊級頁腳,頁面內容足夠長在頁面底部,頁面內容不多,須要緊貼在視口底部。
固定高度的方案:sticky-footer-fixed
main { min-height: calc(100vh - 7em) }
更靈活的方案:sticky-footer
body { display: flex; flex-flow: column; min-height: 100vh; } main { flex: 1; }
ease-out 是 ease-in 的反向版本。
cubic-bezier(x1, y1, x2, y2),把控制錨點的水平座標和垂直座標互換,就能夠獲得任何調速函數的反向版本。
@keyframes bounce { 60%, 80%, to { transform: translateY(400px); animation-timing-function: ease; } 70% { transform: translateY(300px); } 90% { transform: translateY(360px); } } .ball { animation: bounce 3s cubic-bezier(.1, .25, 1 ,.25); }
@keyframes loader { to { background-position: -800px 0; } } .loader { width: 100px; height: 100px; background: url(img/loader.png) 0 0; animation: loader 1s infinite steps(8); }
steps() 會根據你指定的步數進量,把整個動畫切分爲多幀,並且每一個動畫會在幀與幀之間硬切。
關於steps:CSS3 animation屬性中的steps功能符深刻介紹
ch 單位:表示「0」字形的寬度。在等寬字體中,「0」字形的寬度和其餘全部字形的寬度一致。用 ch 單位表示寬度,那取值實際上就是字符的數量。
@keyframes typing { from { width: 0; } } @keyframes caret { 50% { border-color: transparent; } } h1 { width: 15ch; /* 文本的寬度 */ overflow: hidden; white-space: nowrap; border-right: .5em solid; animation: typing 6s steps(15), caret 1s steps(1) infinite; } document.querySelectAll('h1').forEach(function (h1) { var len = h1.textContent.length, s = h1.style; s.width = len + 'ch'; s.animationTimingFunction = "steps("+len+"), steps(1)"; })
@keyframes panoramic { to { background-position: 100% 0; } } .panoramic { width: 150px; height: 150px; background: url(img/naxos-greece.jpg); background-size: auto 100%; animation: panoramic 10s linear infnte alternate; animation-play-state: paused; } .panoramic:hover, .panoramic:focus { animation-play-state: running; }
整張圖片從左滾蛋到右側。
沿着環形進行移動,同時保持本身原本的朝向。
每一個transform-origin都是能夠被兩個translate()模擬出來的。下面兩段代碼是等效的。
transform: rotate(30deg); transform-origin: 200px 300px; transform: translate(200px, 300px) rotate(30deg) translate(-200px, -300px); transform-origin: 0 0;
牢記變形函數並非彼此獨立的。每一個變形函數並非只對這個元素進行變形,而是會把整個元素的座標系統進行變形,從而影響後面的變形操做。這也說明了爲何變形函數的順序是很重要的。
@keyframes spin { from { transform: translateY(150deg) translateY(-50%) rotate(0turn) translateY(-150deg) translateY(50%) rotate(1turn); } to { transform: translateY(150deg) translateY(-50%) rotate(1turn) translateY(-150deg) translateY(50%) rotate(0turn); } } .avatar { animation: spin 3s infinite linear; }
書中記錄的這些效果,都有很詳細的啓發做用,每一個案例都敲一遍,理解了感受css真的有魔力呢。
向該書的做者致敬,表示感謝。