基礎理論
元素的顯示與隱藏
根據不同的需求選擇隱藏方案
如果希望元素不可見,同時不佔據空間,輔助設備無法訪問,同時不渲染,使用script標籤隱藏
<script type="text/html">
<img src="./img/55.png" />
</script>
獲取數據的方法使用 document.querySelector('script').innerHTML
如果希望元素不可見,同時不佔據空間,輔助設備無法訪問,但資源有加載,DOM可訪問,則可以直接使用display:none隱藏
.dn{
display:none;
}
如果希望元素不可見,同時不佔據空間,輔助設備無法訪問,但顯隱的時候可以有transition淡入淡出效果
.hidden {
position: absolute;
visibility: hidden;
}
如果希望元素不可見,不能點擊,輔助設備無法訪問,但佔據空間保留則可以使用visibility:hidden隱藏
.vh {
visibility: hidden;
}
如果希望元素不可見,不能點擊,不佔據空間,但鍵盤可訪問,則可以使用clip裁剪隱藏
.clip {
position: absolute;
clip: rect(0 0 0 0);
}
案例:1.請帖生成封面。2.鍵盤使用快捷鍵但不顯示按鈕(使用 accesskey)
如果希望元素不可見,不能點擊,但佔據空間,且鍵盤可訪問,則可以使用relative隱藏。如果條件允許,也就是上一層層疊上下文之間設置了背景色,則可以使用更友好的z-index負值隱藏
.out {
position: relative;
left:-999em;
}
.lower {
position: relative;
z-index: -1;
}
如果希望元素不可見,但可以點擊,而且不佔據空間,則可以使用透明度
.opacity {
position: absolute;
opacity: 0;
}
如果希望元素不可見,但位置保留,依然可以點可以選,則直接讓透明度為0
.opacity{
opacity: 0;
}
如果希望元素在顯示時有一個 transition 動畫,可以使用 max-height 進行隱藏
.hidden {
max-height: 0;
overflow: hidden;
}
display與元素的顯隱
基礎瞭解:無法點擊,無法使用屏幕閲讀器等輔助設備訪問,佔據空間消失
深層瞭解:img標籤上或父元素設置 display:none 都會加載資源。但是 background-image 請求的資源在該標籤上或父元素設置 display:none 都不會加載資源(safari和chrome驗證),在計數中設置了display:none的元素不被計入。會對 IntersectionObserver 造成影響
visibility與元素的顯隱
基礎瞭解:無法點擊,無法使用屏幕閲讀器等輔助設備訪問,佔據空間不消失
深層瞭解:visibility 具有繼承性,父級設置 visibility:hidden 後子級可以設置 visibility:visible 顯示子元素。設置了 visibility:hidden 的元素會加載img資源也會加載 background-image 資源。同時也會被納入計數。visibility 屬性被納入 transition 的範圍內,因此可利用該屬性展示元素從隱藏到顯示的過渡效果。但是該屬性不會對 IntersectionObserver 造成影響,也就是説如果彈窗是從隱藏到顯示使用了該屬性的話,對它進行埋點是無效的。
文本的換行
word-break
當行尾放不下一個單詞時,決定單詞內部該怎麼擺放(決定不斷行單詞的長度)
nomal:默認值,默認的換行規則(CJK文本斷行,英文單詞不斷行,空格斷行)
break-all:對於non-CJK(中日韓)文本,可在任意地方斷行
keep-all:CJK文本不斷行,non-CJK文本表現形式如同nomal
word-wrap
是用來説明當一個不能被分開的字符串太長而不能填充其包裹盒時,為防止其溢出,瀏覽器是否允許這樣的單詞斷詞(沒有換行點的單詞在句尾放不下時,決定單詞是否斷詞)
nomal:默認值,行只能在正常的單詞斷點處中斷。(例如兩個單詞之間的空格)。
break-word:表示如果行內沒有多餘的地方容納該單詞到結尾,則那些正常的不能被分割的單詞會被強制分割換行。
white-space
如何處理元素中的空白
nomal:默認值,連續的空白符被合併,換行符被當做空白符處理
nowrap:連續的空白符被合併,文本內的換行符無效(
有效)
pre:連續的空白符會被保留,在遇到換行符或者
元素時才會換行
pre-wrap:連續的空白符會被保留,在遇到換行符或者
元素,或者為了填充行框盒子(line-box)時才會換行
pre-line:連續的空白符會被合併,在遇到換行符或者
元素,或者為了填充行框盒子(line-box)時才會換行
line-break
中文標點的換行規則,比如。是避首標點,《是避尾標點,通過此屬性控制CJK文本標點的換行規則
auto:使用默認的換行規則。
loose: 使用限制性最小的換行規則分隔文本。通常用於短行,如在報紙上。
normal:使用最普通的換行規則。
strict: 使用最嚴格的換行規則。
anywhere:任意位置都可以作為換行點,包括任意的標點。
<wbr>
這是html元素,寬度不夠,在我這裏換行;寬度足夠,還是一行顯示
實現原理
wbr::after{
content: '\00200B'
}
光標屬性cursor
https://developer.mozilla.org...
flex子項最終尺寸計算規則
一個flex子項的最終尺寸是基礎尺寸(或內容尺寸),彈性增長或收縮,最大最小尺寸共同作用的結果
最終尺寸計算的優先級是:
最大最小尺寸限制 > 彈性增長或收縮 > 基礎尺寸
- 基礎尺寸有
flex-basis屬性或width屬性,以及box-sizing盒模型共同決定 - 內容尺寸指最大內容寬度,當沒有設置基礎尺寸時會頂替基礎尺寸的角色
- 彈性增長指的是
flex-grow屬性,彈性收縮指的是flex-shrink屬性 - 最大尺寸主要受
max-width屬性顯示;最小尺寸受最小內容寬度,width屬性和min-width屬性共同影響
flex容器:
flex-wrap:nowrap;
flex-direction:row;
justify-content:flex-start;
align-items:stretch;為默認值flex: 0 1 auto 這是flex子項的默認值,代表flex-grow:0,flex-shrink:1,flex-basis: auto
最小尺寸計算規則
- 如果
min-width屬性值不是auto,則元素的最小尺寸就是就是min-width的屬性值,此時width屬性無法影響最小尺寸,哪怕width的屬性值大於min-width的屬性值。 - 比較
width的屬性的計算值和最小內容寬度的大小,較小的值就是元素的最小尺寸。 - 如果
width的屬性值和min-width的屬性值均為auto,則元素的最小尺寸就是最小內容寬度。 - 如果flex子項設置了
overflow:hidden,且最小尺寸是由是否最小內容寬度決定的,則最小尺寸無效。
基礎尺寸計算規則
- 如果
flex-basis屬性和width屬性同時設置了具體的數值,width屬性值會被忽略,優先使用flex-basis作為基礎尺寸。 - 如果
flex-basis的屬性值是初始值auto,則會使用width屬性設置的長度值作為基礎尺寸。 - 如果
flex-basis和width的屬性值都是auto,則會使用flex子項的最大內容寬度作為基礎尺寸
彈性增長或收縮何時作用
- 如果容器尺寸足夠並且子元素的屬性值包含
flex-grow不為0則啓用彈性增長規則 - 容器尺寸足夠:在容器
flex-wrap:wrap狀態下,n個子元素的基礎尺寸相加寬度少於容器寬度,n+1個子元素的基礎尺寸相加大於容器,且這n個子元素中具有flex-grow不為0的元素,則這n個子元素具備彈性增長的條件。在容器flex-wrap:nowrap狀態下,所有子元素基礎尺寸相加寬度少於容器寬度。 - 如果容器尺寸不足並且子元素的屬性值包含
flex-shrink不為0則啓用彈性收縮規則 - 容器尺寸不足:在容器
flex-wrap:wrap狀態下,子元素的基礎尺寸大於容器寬度,且子元素的flow-shrink不為0,則這個子元素具備彈性收縮條件。在容器flex-wrap:nowrap狀態下,所有子元素的基礎寬度少於容器寬度,且至少有一個子元素的flex-shrink不為0,則flex-shrink不為0的子元素具備彈性收縮條件。 - 彈性增長,增長的部分是可分配空間,計算規則是容器寬度-元素基礎尺寸
- 彈性收縮,收縮的部分是有
flex-shrink不為0元素的寬度,最多可以收縮至元素最小尺寸。
最終尺寸計算規則-總結
- 如果沒有彈性收縮或增長,則元素在最大尺寸和最小尺寸範圍內使用基礎尺寸
- 如果元素能夠彈性增長或收縮,在容器寬度足夠的情況下使用彈性增長規則,在容器寬度不足的情況下使用彈性收縮規則,同一行只可能應用一種規則
選擇器
選擇器優先值計算
| 選擇器 | 計算值 | 計算細則 |
|---|---|---|
| * {} | 0 | 1個0級統配選擇器,優先級數值為0 |
| dialog {} | 1 | 1個1級標籤選擇器,優先級數值為1 |
| ui > li {} | 2 | 2個1級標籤選擇器,1個0級選擇器,優先級數值為2 |
| li > ol + ol {} | 3 | 3個1級標籤選擇器,2個0級選擇器,優先級數值為3 |
| .foo {} | 10 | 1個2級類名選擇器,優先級數值為10 |
| a:not([rel=nofollow]) {} | 11 | 1個2級屬性選擇器,1個1級標籤選擇器,1個0級否定偽類,優先級數值為11 |
| a:hover {} | 11 | 1個1級標籤選擇器,1個2級偽類,優先級數值為11 |
| ol li.foo {} | 12 | 2個1級標籤選擇器,1個2級類名選擇器,優先級數值為12 |
| li.foo.bar {} | 21 | 1個1級標籤選擇器,2個2級類名選擇器,優先級數值為21 |
| #foo {} | 100 | 1個3級ID選擇器,優先級數值為100 |
| #foo .bar p {} | 111 | 1個3級ID選擇器,1個2級類名選擇器,1個1級標籤選擇器,優先級數值為111 |
相同計算值下遵循後來居上原則,後面的優先級更高
命名靈感
從HTML標籤尋找靈感
.cs-module-header {}
.cs-module-body {}
.cs-module-aside {}
.cs-module-main {}
.cs-module-nav {}
.cs-module-section {}
.cs-module-content {}
.cs-module-summary {}
.cs-module-detail {} // 詳情
.cd-module-option {}
.cs-module-img {}
.cs-module-footer {}
.cs-module-ui {}
.cs-module-li {} // 列表子項
.cs-module-a {} // 鏈接
.cs-module-g {} // 組
.cs-module-desc {} // 描述
.cs-module-x {} // 容器盒子
從HTML特定屬性值中尋找靈感
.cs-radio {}
.cs-checkbox {}
.cs-range {}
.cs-tspan-email {}
.cs-tspan-number {}
.cs-tspan-color {}
.cs-tspan-tel {}
.cs-tspan-date {}
.cs-tspan-url {}
.cs-tspan-time {}
.cs-tspan-file {}
從無障礙訪問的role屬性值中尋找靈感
.cs-grid {}
.cs-grid-cell {}
.cs-log {}
.cs-menu {}
.cs-menu-bar {}
.cs-menu-item {}
.cs-region {} // 不能被其他role描述,但是很重要的部分
.cs-banner {} // 橫幅廣告
.cs-slider {}
.cs-tab {}
.cs-tab-list {}
.cs-tab-pannel {}
.cs-tooltip {}
.cs-tree {}
從CSS偽類和HTML布爾屬性中尋找靈感
.active {}
.disabled {}
.selected {}
.checked {}
.invalid {} // 出錯狀態
體驗優化
圖片加載失敗體驗優化
<img src="xxx.png" alt="圖片封面" onerror="this.classList.add('error');">
img.error {
display: inline-block;
transform: scale(1);
content: '';
color: transparent;
}
/* 替換圖片 */
img.error::before {
content: '';
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
background: #f5f5f5 url(break.svg) no-repeat center / 50% 50%;
}
/* alt 提示 */
img.error::after {
content: attr(alt);
position: absolute;
left: 0; bottom: 0;
width: 100%;
line-height: 2;
background-color: rgba(0,0,0,.5);
color: white;
font-size: 12px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
點擊體驗優化
移動端按鈕可點擊範圍放大
.mobi-btn {
border: 8px solid transparent;
}
鍵盤體驗優化
可訪問性-焦點控制
tabindex = "-1"
元素可以被鼠標或JS focus但不能被鍵盤focus
tabindex = "0"
最後一個被focus的元素
tabindex >= "1"
越小優先級越高
若進入網頁沒有點擊則按照1,2,...,0
若點擊則定位到點擊的主體,按下tab尋找到第一個有focus的元素,再次按下根據該元素的tabindex尋找下一個焦點
:focus-visible
讓我們知道元素的聚焦行為是鍵盤觸發還是鼠標觸發
// 鼠標觸發
:focus:not(:focus-visible) {}
// 鍵盤觸發
:focus:focus-visible {}
當前獲得焦點的元素
document.activeElement
檢測文檔是否獲取了焦點
document.hasFocus()
滾動體驗優化
overscroll-behavior
overscroll-behavior: [ contain | none | auto ]{1,2} 當只有一個值時代表水平垂直方向都是該值,有兩個值時第一個代表水平方向第二個代表垂直方向
auto:滾動到邊緣後繼續滾動外部的可滾動容器
contain:默認的滾動溢出行為只會表現在當前元素的內部,不會對相鄰的滾動區域進行滾動。
none:相鄰的滾動區域不會發生滾動,並且會阻止默認的滾動溢出行為。
scroll-behavior
在可滾動的容器上使用,常用於到達頂部
auto:默認值
smooth:平滑滾動,與 ant-design 的 scrollToFirstError 搭配效果佳
overflow-anchor
auto: 默認值,該行為會調整位置以最大程度的減少內容偏移(例如上方圖片的突然加載會無感知)
none:退出瀏覽器滾動錨定行為
隱藏滾動條,同時元素可滾動
.scroll-none {
scrollbar-width: none;
}
// chrome 私有方法
.scroll-none::-webkit-scrollbar {
width:0; height:0;
}
跳轉體驗優化
PC端跳轉同一個地址不創建新的tab頁
<a href="https://www.baidu.com" target="bd">點擊進入百度</a>
target相同時會指向同一個tab頁
輸入體驗優化
cater-color屬性改變插入光標顏色
cater-color: red
移動端喚起數字鍵盤
驗證碼:<input inputmode="numeric">
拉伸行為體驗優化
rezize
none: 默認值,沒有拉伸效果,可以用來種植 textarea 元素默認的拉伸行為
both:既可以水平方向拉伸,也可以垂直方向拉伸
horizontal:僅可以水平方向上拉伸
vertical:僅可以垂直方向上拉伸
生效條件
塊級元素且 overflow 的屬性值不是 visible
限制拉伸範圍
使用 max-width,max-height,min-width,min-height 屬性
選擇行為體驗優化
user-select
text:默認值,文字和圖片可以被選中
none:禁止圖文被選中
all:被低估的一個屬性值,設置了該屬性的圖文內容都會被選中
::selection
被選中時偽類,全局設置時可設置品牌顏色為背景,合適顏色為字體顏色
::selection {
color: hunlijiColor;
background: hunlijuBackgroundColor;
}
刷新體驗優化
刷新時滾動條回到頂部
if (history.scrollRestoration) {
history.scrollRestoration = 'manual';
}
打印行為體驗優化
控制打印樣式的媒體查詢
@media print {
header{
display:none;
}
}
是否進行精確打印
color-adjust
economy:默認值,可能會將背景不打印
exact:精確打印
table{
-webkit-print-color-adjust: exact;
color-adjust: exact;
}
使該元素另起一頁打印
break-before:page
性能優化
will-change
will-change 的作用有兩個,一個是創建合成層,一個在真正的行為觸發之前告訴瀏覽器:“我要變化了,你要做好準備”
如何正確的使用
will-change 不應該被設置在默認狀態中且需要及時銷燬,理想中的應用場景應該是 hover 狀態下
// good
.will-change-parent:hover .will-change{
will-change:transform;
}
.will-change {
transition: transform 0.3s;
}
.will-change:hover {
transform: scale(1.5)
}
// bad
.will-change {
transition: transform 0.3s;
}
.will-change:hover{
will-change: transform;
transform: scale(1.5);
}
如果點擊按鈕,某個元素執行動畫,先執行的是 mousedown 事件,之後執行的是 click 事件
dom.onmousedown = function() {
target.style.willChange = 'transform'
}
dom.onclick = function() {
// target元素執行動畫
}
target.onanimationend = function() {
// 動畫結束,用回調函數移除will-change屬性
this.style.willChange = 'auto'
}
創建合成層
無法複製加載中的內容
- 合成層的位圖會交由
GPU合成,比CPU處理要快得多 - 當需要
repaint時,只需要repaint本身,不會影響其他層 - 元素提升為合成層後,
transform和opacity不會觸發repaint,如果不是合成層則依舊會觸發repaint
避免隱式創建合成層及優化
合成層比較佔用內存,假如一個合成層的寬高為100px 100px,則合成層佔用內存的計算方式為100100*3 = 30000Byte = 30KB
當元素交疊,處在下方的元素成為了合成層,上方的元素隱式變成了合成層
- 可以將必須合成層的層級提升至較高層級,則其他交疊層級沒有該層級高就不會隱式創建合成層
- 動畫使用
transform實現,一方面如果不涉及到translateZ則不會創建合成層,一方面生成層疊上下文不會影響到別的層疊上下文渲染 - 通過減少寬高再進行
scale放大的方式可以有效減少合成層使用的內存
SEO
H1標籤一個頁面只能用一個
同一網頁通過多個網址訪問指定規範網址
<link rel="canonical" href="http://www.hunliji.com/merchant/detail_1378">
關鍵詞
<meta data-hid="keywords" name="keywords" content="關鍵詞1,關鍵詞2">
詳細描述
<meta data-hid="description" name="description" content="描述內容,字數在0-200字為佳">
不需要抓取的鏈接nofollow
<a href="www.baidu.com" rel="nofollow">
指定為外部鏈接external
<a href="www.baidu.com" rel="external nofollow">
指定頁面圖標
<link rel="icon" type="image/png" href="/path/to/icons/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/path/to/icons/favicon-32x32.png" sizes="32x32">
很少用的屬性
將中文簡體轉換為繁體
蘋方字體有效,老老實實做i18n吧哈哈
font-variant-east-asian: traditional;