Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
代CSS強大的令人難以置信。
這次我們來用 CSS 實現這樣一個功能:有多個寬度不同的標簽水平排列,當外層寬度不足時,會提示超出的數量,演示效果如下
如果讓我用 JavaScript來實現估計都有點折騰,畢竟寬度都是動態的,要監聽各部分的尺寸變化,包括標簽的位置和外層的寬度,總之不是一兩行代碼就能搞定的。
現如今,純CSS也能完美的實現這樣的效果,而且比 JS 實現更加簡單,一起來看看吧
很多時候,CSS并沒有直接的實現方式,需要“繞”點彎路,將需求拆分成很多小點,然后逐一突破。
回到本文這里,其實有幾個問題需要考慮:
關于第3點,其實在之前這篇文章中有詳細介紹,有興趣可以回顧一下,非常有意思
純 CSS 檢測文本是否溢出
那么第一點,CSS有沒有什么方式可以統計數量呢?
沒錯,相信很多小伙伴已經猜到了,就是利用 CSS計數器,示意如下
counter-reset: num var(--num);
counter-increment: num;
::after{
content: "+"counter(num);
}
關于計數器,我之前也在很多文章中有用到
你可能不需要 JS!CSS實現一個計時器
如何讓CSS計數器支持小數的動態變化?
還在使用定時器嗎?CSS 也能實現電子時鐘
動畫合成小技巧!CSS 實現動感的倒計時效果
自定義計數器小技巧!CSS 實現長按點贊累積動畫
然后是第二點,CSS有什么方式可以知道元素是出去了還是在視野之內呢?
如果是用 JS來判斷的話,最穩妥的方式應該Intersection Observer(交叉觀察者),相信很多同學都用過,這個在圖片懶加載非常有用
交叉觀察器 API - Web API 接口參考 | MDN (mozilla.org)[1]
那么,CSS中有什么類似的呢?沒錯,還是之前提到過的CSS滾動驅動動畫。
不過這里用到的是視圖進度,也就是關注的是元素自身位置,元素進入到容器范圍之內就會觸發動畫,非常類似 JS中的Intersection Observer
tag{
animation: appear;
animation-timeline: view(inline);
animation-range: contain;
}
@keyframes appear{
to {
background-color: #9747FF;
}
}
這里就不詳細介紹了,有興趣回顧之前這篇文章
CSS 滾動驅動動畫終于正式支持了~
好了,關鍵原理就這些了,我們需要做的就是想辦法將「計數器」和「元素進出容器范圍」關聯起來就行了,接著往下看
利用 CSS 計數器,我們可以很輕松的統計元素的數量。
先簡單布局一下文章開頭的例子,HTML如下所示
<div class="con">
<a class="tag">HTML</a>
<a class="tag">CSS</a>
<a class="tag">JavaScript</a>
<a class="tag">Flutter</a>
<a class="tag">Vue</a>
<a class="tag">React</a>
<a class="tag">Svelte</a>
</div>
<span class="num"></span><!--用來計數的標簽-->
然后美化一下
.con{
display: flex;
gap: 5px;
padding: 5px;
overflow: hidden;
}
.tag{
padding: .2em .5em;
background-color: #c49ef5;
color: #fff;
border-radius: 4px;
animation: appear;
}
.num::after{
content: "+0";
padding: .2em .5em;
background-color: #FFE8A3;
color: #191919;
border-radius: 4px;
}
這樣就得到了水平排列的 tag 布局(超出隱藏),后面跟一個數字
現在我們定義一個計數器,然后通過每個tag進行累計,有多個tag相當于多少次累加,最后在::after中顯示出來
.con{
counter-reset: num; /*計數器初始值,默認為0*/
}
.tag{
counter-increment: num; /*計數器增量值,默認為1*/
}
.num::after{
content: "+"counter(num);
}
默認計數器的起始值是 0,每次累計是1,所以這里最后得到了7,這樣就能實時統計元素的數量了
當然,我們也可以自定義這些默認值,比如
.con{
counter-reset: num 10;
}
.tag{
counter-increment: num -1;
}
這種情況下,起始值是10,增量值是-1,所以最后得到了3,如下
那么,該如何統計容器之外的標簽數量呢?
這里我們要利用CSS 視圖進度時間軸,也就是觀察元素自身的位置,在進入到容器范圍之內執行動畫。
拿上面這個例子,我們給標簽添加一個動畫,讓標簽在進入到容器之內時變個顏色,實現如下
.tag{
animation: appear;
animation-timeline: view(inline);
}
@keyframes appear{
to {
background-color: #4d47ff;
}
}
由于是水平方向,所以這里需要設置view(inline) ,效果如下
好像不是很明顯?這是因為動畫是在整個視區內過渡的,我們可以改變動畫時間線的區間animation-range,讓這個動畫在進出的一瞬間就變化
.tag{
animation: appear;
animation-timeline: view(inline);
animation-range: contain;
}
@keyframes appear{
from,to {
background-color: #4d47ff;
}
}
效果如下
那么,這個效果和前面的計數器有什么關聯呢?
從效果上來看,在視區內會執行一個動畫,如果在這個動畫中加入計數器的累加會怎么樣呢?先去除原先的累加器
.tag{
/* counter-increment: num; */
}
@keyframes appear{
from,to {
background-color: #4d47ff;
counter-increment: num;
}
}
效果如下
可以看到計數器已經生效了,不過現在統計的在「可視區內」標簽的數量。而我們要統計的是「可視區外」的數量,好像反過來了,如何實現呢?
這里有兩種思路。
第一種,用總數減去可視區內的數量,不就行了嗎?由于現在動畫是針對可視區內的,我們可以給計數器設置一個初始值,就是總量,然后動畫中給累加值設置為-1,就相當于減去當前數量了,實現如下
.con{
counter-reset: num 7;
}
@keyframes appear{
from,to {
background-color: #4d47ff;
counter-increment: num -1;
}
}
這樣就完美統計出了可視區外的數量了
還有一種方式,我覺得更加巧妙,需要反向思考。原理是重置當前的累加值,比如默認情況下,正常累加,進入可視范圍,把累加值設置為0,不就相當于可視區外的正常累加了嗎?
.tag{
counter-increment: num;
}
@keyframes appear{
from,to {
background-color: #4d47ff;
counter-increment: num 0;
}
}
同樣能達到相同的效果
現在基本已經達到我們需要的效果了
首先是,在超出范圍時,需要在邊緣出添加一個半透明蒙層,這樣體驗效果會更好。
半透明蒙層很好實現,只需要添加一個水平漸變的mask遮罩就行了
.con{
-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
}
效果如下
那么,如何在沒有超出時,不出現這個遮罩呢?
這個其實在之前的文章中有詳細介紹了,建議回顧一下
純 CSS 檢測文本是否溢出
利用CSS滾動驅動動畫,可以檢測容器是否可滾動,也就是是否超出。所以我們只需要將遮罩放在滾動驅動動畫里就行了,關鍵實現如下
.con{
animation: check;
animation-timeline: scroll(x self);
}
@keyframes check{
from,to {
-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
}
}
效果如下
還有一個問題,希望在沒有超出的時候不顯示后面的數量。
關于這個,我本來是打算用樣式查詢來實現,但是遇到了一個問題,由于樣式查詢只能匹配到子元素,所以不得不將顯示數量的標簽放到.con容器內。但是這樣一來,mask遮罩就會出現問題,就像這樣
遮罩層連同數量標簽一起被裁剪了!
于是又想出了另一種方案,這個在以前的布局中其實用到的更多,那就是負margin。
實現很簡單,給標簽容器一個的負margin-right,這樣,右邊的數量就會被左邊的標簽蓋住,比如
.con{
margin-right: -20px;
}
效果如下
是不是已經被蓋住一部分了?我們繼續向左偏移
.con{
margin-right: -50px;
}
這樣就完全看不到右邊的數量了
那么,如何在超出時顯示數量呢?這里就體現出負margin的好處了,可以借助前一個元素來隱藏后一個元素,在這里,我們直接在前面的動畫中還原margin就行了
.con{
animation: check;
animation-timeline: scroll(x self);
}
@keyframes check{
from,to {
-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
margin-right: 0;
}
}
這樣就完美實現了文章開頭所示效果了
你也可以訪問以下鏈接來體驗真實效果(Chrome115+)
以上就是本文的全部內容了,不知道你學會了嗎?下面總結一下實現重點:
[1]交叉觀察器 API - Web API 接口參考 | MDN (mozilla.org): https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API
[2]CSS auto tag num (juejin.cn): https://code.juejin.cn/pen/7352565668073439241
[3]CSS auto tag num (codepen.io): https://codepen.io/xboxyan/pen/rNbYpZV
作者:XboxYan
來源-微信公眾號:前端偵探
出處:https://mp.weixin.qq.com/s/_m5UxLQQtDU1GxbLRnCUhQ
增的結構標簽
section元素
表示頁面中的一個內容區塊,比如章節、頁眉、頁腳或頁面的其他部分??梢院蚳1、 h2...等元素結合起來使用,表示文檔結構。
例:HTML5中<section>...</section>;HTML4中<div>...</div>。
article元素
表示頁面中一塊與上下文不相關的獨立內容。比如一篇文章。
aside元素
表示article元素內容之外的、與article元素內容相關的輔助信息。
header元素
表示頁面中一個內容區塊或真個頁面的標題。
hgroup元素
表示對真個頁面或頁面中的一個內容區塊的標題進行組合。
footer元素
表示整個頁面或頁面中一個內容區塊的腳注。一般來說,他會包含創作者的姓名、創作日期以及創作者的聯系信息。
nav元素
表示頁面中導航鏈接的部分。
figure元素
表示一段獨立的流內容,一般表示文檔主體流內容中的一個獨立單元。使用figcaption元素為figure元素組添加標題。
figure 定義媒介內容的分組, 以及它們的標題。
figcaption 定義 figure 元素的標題。
例如:
<figure>
<figcaption>PRC</figcaption>
<p>The People's Republic of China was born in 1949</p>
</figure>
HTML4中常寫作
<dl>
<h1>prc</h1>
<p>The People's Republic of China was born in 1949</p>
</dl>
新增的其他元素
video元素
定義視頻。像電影片段或其他視頻流。例:
<video src="movie.ogg" controls="controls">video元素</video>
HTML4中寫法:
<object type="video/ogg" data="move.ogv">
<param name ="src" value="movie.ogv">
</object>
audio元素
定義音頻。如音樂或其他音頻流。例:
<audio src ="someaudio.wav">audio元素</audio>
html4中寫法:
<object tyle="application/ogg" data="someaudio.wav">
<param name ="src" value= "someaudio.wav">
</object>
embed元素
用來嵌入內容(包括各種媒體)。格式可以是Midi、Wav、AIFF、AU、MP3,flash等。例:<embed src="flash.swf" />
HTML4中代碼示例<object data="flash.swf" type="application/x-shockwave-flash"><object>
mark元素
主要用來在視覺上向用戶呈現哪些需要突出顯示或高亮顯示的文字。典型應用搜索結果中高亮顯示搜素關鍵字。
HTML5<mark></mark>;HTML4 <span></span>。
progress元素
表示運行中的進程,可以使用progress元素顯示JavaScript中耗時時間函數的進程。等待中……、請稍后等。<progress></progress>。
time元素
表示日期或時間,也可以兩者同時。
ruby元素
定義 ruby 注釋(中文注音或字符)。
與 <ruby> 以及 <rt> 標簽一同使用。ruby 元素由一個或多個字符(需要一個解釋/發音)和一個提供該信息的 rt 元素組成,
還包括可選的 rp 元素,定義當瀏覽器不支持 "ruby" 元素時顯示的內容。
<ruby>
漢朝<rt><rp>(</rp>西漢和東漢<rp>)</rp></rt>
</ruby>
rt元素
定義字符(中文注音或字符)的解釋或發音。
rp元素
在 ruby 注釋中使用, 以定義不支持 ruby 元素的瀏覽器所顯示的內容。
wbr元素
表示軟換行。與br元素的區別:br元素表示此處必須換行;wbr表示瀏覽器窗口或父級元素足弓寬時(沒必要換行時),
不換行,而寬度不夠時主動在此處換行。
canvas元素
定義圖形,比如圖表和其他圖像。<canvas> 元素只是圖形容器(畫布),必須使用腳本來繪制圖形。
<canvas id="myCanvas"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
var ctx=canvas.getContext('2d');
ctx.fillStyle='#FF0000';
ctx.fillRect(0,0,80,100);
</script>
command元素 各版本瀏覽器支持有問題
表示命令按鈕,比如單選按鈕、復選框或按鈕。
只有當 command 元素位于 menu 元素內時,該元素才是可見的。否則不會顯示這個元素,但是可以用它規定鍵盤快捷鍵。。
<menu>
<command onclick="alert('Hello World')">
Click Me!</command>
</menu>
details標簽
用于描述文檔或文檔某個部分的細節 。
可與 summary 標簽配合使用,summary可以為 details 定義標題。
標題是可見的,用戶點擊標題時,會顯示出 details。summary應該是details的第一個子元素。
<details>
<summary>迪麗熱巴</summary>
<p>迪麗熱巴(Dilraba),1992年6月3日出生于新疆烏魯木齊市,中國內地影視女演員。</p>
</details>
fieldset標簽
組合表單中的相關元素
fieldset 標簽用于從邏輯上將表單中的元素組合起來。
legend 標簽為 fieldset 元素定義標題。
<form>
<fieldset>
<legend>健康信息</legend>
身高:<input type="text" />
體重:<input type="text" />
</fieldset>
</form>
datalist標簽
定義選項列表。請與 input 元素配合使用該元素,來定義 input 可能的值。
datalist 及其選項不會被顯示出來,它僅僅是合法的輸入值列表。使用 input 元素的 list 屬性來綁定 datalist。
<input id="myCar" list="cars" />
<datalist id="cars">
<option value="BMW">
<option value="Ford">
<option value="Volvo">
</datalist>
datagrid標簽 如何用?
定義可選數據的列表。datagrid 作為樹列表來顯示。
如果把 multiple 屬性設置為 true,則可以在列表中選取一個以上的項目。
keygen標簽 如何用?
標簽規定用于表單的密鑰對生成器字段。
當提交表單時,私鑰存儲在本地,公鑰發送到服務器。
<form action="demo_keygen.asp" method="get">
Username: <input type="text" name="usr_name" />
Encryption: <keygen name="security" />
<input type="submit" />
</form>
output標簽
定義不同類型的輸出,比如腳本的輸出。
<form action="form_action.asp" method="get" name="sumform">
<output name="sum"></output>
</form>
source標簽
標簽為媒介元素(比如 <video> 和 <audio>)定義媒介資源。
menu標簽
定義菜單列表。當希望列出表單控件時使用該標簽。注意與nav的區別,menu專門用于表單控件。
<menu>
<li><input type="checkbox" />Red</li>
<li><input type="checkbox" />blue</li>
</menu>
abbr: 標記一個縮寫
The <abbr title="People's Republic of China">PRC</abbr> was founded in 1949.
顯示結果
The PRC was founded in 1949.
mark標簽
定義有記號的文本。
<mark>有記號的文本</mark>
progress 定義任何類型的任務的進度。
<progress min="0" max="100" value="60"></progress>
Flask 的 Jinja2 模板引擎中,使用 block 標簽可以在基模板(父模板)中聲明替換的區域,子模板則可以繼承父模板并重寫這些 block 區域中的內容。向 Flask 的父模板中添加或追加內容,你可以使用 super() 函數來引用父模板中的原始內容。
假設你有一個父模板 base.html,其中定義了兩個 block:
<!-- base.html -->
<html>
<head>
...
{% block head %}
<!-- 父模板的 head 內容 -->
{% endblock %}
</head>
<body>
{% block content %}
<!-- 父模板的主體內容 -->
{% endblock %}
</body>
</html>
如果你想在子模板中不僅替換這些 block,還想保留并在其前面或后面追加內容,你可以在子模板中這樣寫:
<!-- child.html -->
{% extends "base.html" %}
{% block head %}
{{ super() }} <!-- 這里使用 super() 調用父模板的原始內容 -->
<!-- 子模板追加的頭部內容 -->
<link rel="stylesheet" href="style.css">
{% endblock %}
{% block content %}
<!-- 子模板的主體內容 -->
<div>這里是子模板獨有的內容。</div>
<!-- 還可以在后面追加 super() 來保留父模板的內容 -->
{{ super() }}
{% endblock %}
在這個例子中,child.html 繼承了 base.html 并重寫了 head 和 content 塊。通過調用 {{ super() }},子模板 child.html 在新內容的前后分別保留了父模板 base.html 中相應塊的內容。這允許你在現有內容上擴展,而不是替換掉整個塊的內容。
總之,通過 block 和 super(),你可以很靈活地控制模板繼承的具體行為,既可以重寫整塊內容,也可以在不修改父模板的情況下對其內容進行擴展。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。