CSS 容器查詢的烏鴉技巧:更接近容器查詢
我們再次強調:CSS 中需要容器查詢!看起來我們正朝著這個方向前進。
在構建網站組件時,你並不總是知道組件將如何使用。它可能與瀏覽器窗口一樣寬。 也許兩個組件並排放置。 也許它在一個狹窄的列中。組件的寬度並不總是與瀏覽器窗口的寬度相關。
通常情況下,你會發現使用基於容器的CSS 組件查詢非常方便。如果你在網上搜索解決方案,你可能會發現幾種基於JavaScript 的解決方案。但這些解決方案是有代價的:額外的依賴項、需要JavaScript 的樣式以及被污染的應用程序邏輯和設計邏輯。
我堅信關注點分離,而佈局是CSS 的關注點。例如,儘管IntersectionObserver API 很好,但我希望CSS 中有像:in-viewport
這樣的東西!因此,我繼續尋找僅限CSS 的解決方案,並發現了Heydon Pickering 的“Flexbox 神聖信天翁”。這對於列來說是一個不錯的解決方案,但我想要更多。原始信天翁有一些改進(如“不神聖的信天翁”),但它們仍然有點笨拙,所有發生的事情只是行到列的切換。
我仍然想要更多!我想更接近實際的容器查詢!那麼,CSS 提供了什麼我可以利用的呢?我具有數學背景,因此像calc()
、 min()
、 max()
和clamp()
這樣的函數是我喜歡和理解的東西。
下一步:用它們構建一個類似容器查詢的解決方案。
目錄:
- 為什麼是“烏鴉”?
- CSS 中的數學函數
- 步驟1:創建配置變量
- 步驟2:創建指示器變量
- 步驟3:使用指示器變量選擇區間值
- 步驟4:使用
min()
和一個極大的整數來選擇任意長度的值 - 步驟5:將所有內容整合在一起
- 其他?
- 高度呢?
- 顯示和隱藏內容呢?
- 關鍵點
- 附加內容
- 最後的想法
想在繼續閱讀之前看看可能實現什麼嗎?這是一個展示本文中討論的想法所能實現的功能的CodePen 合集。
為什麼是“烏鴉”?
這項工作受到Heydon 的信天翁的啟發,但該技術可以做更多技巧,所以我選擇了一隻烏鴉,因為烏鴉是非常聰明的鳥。
回顧:CSS 中的數學函數
calc()
函數允許在CSS 中進行數學運算。另外,可以組合單位,因此像calc(100vw - 300px)
這樣的操作是可能的。
min()
和max()
函數接受兩個或多個參數並返回最小或最大參數(分別)。
clamp()
函數非常有用,它類似於min()
和max()
的組合。函數clamp(a, x, b)
將返回:
- 如果x 小於a,則返回a
- 如果x 大於b,則返回b
- 如果x 在a 和b 之間,則返回x
所以它有點像clamp(最小值, 相对值, 最大值)
。可以將其視為min(max(a,x),b)
的簡寫。如果你想了解更多信息,這裡有更多關於這些的信息。
我們還將在本文中大量使用另一個CSS 工具:CSS 自定義屬性。這些就像--color: red;
或--distance: 20px;
一樣。本質上是變量。我們將使用它們來使CSS 更簡潔,例如避免過多地重複自己。
讓我們開始使用這個烏鴉技巧吧。
步驟1:創建配置變量
讓我們創建一些CSS 自定義屬性來進行設置。
我們希望查詢基於什麼基本大小?由於我們正在尋求容器查詢行為,這將是100%——使用100vw 將使其行為類似於媒體查詢,因為這是瀏覽器窗口的寬度,而不是容器!
<code>--base_size: 100%;</code>
現在我們考慮斷點。字面意思是容器寬度,我們希望在此處中斷以應用新的樣式。
<code>--breakpoint_wide: 1500px; /* 大于1500px 将被视为宽*/ --breakpoint_medium: 800px; /* 从801px 到1500px 将被视为中等*/ /* 小于或等于800px 将被视为小*/</code>
在運行示例中,我們將使用三個區間,但此技術沒有限制。
現在讓我們定義一些我們希望為斷點定義的區間返回的(CSS 長度)值。這些是字面值:
<code>--length_4_small: calc((100% / 1) - 10px); /* 根据你的需求更改*/ --length_4_medium: calc((100% / 2) - 10px); /* 根据你的需求更改*/ --length_4_wide: calc((100% / 3) - 10px); /* 根据你的需求更改*/</code>
這是配置。讓我們使用它!
步驟2:創建指示器變量
我們將為區間創建一些指示器變量。它們有點像布爾值,但帶有長度單位(0px 和1px)。如果我們將這些長度作為最小值和最大值來限制,那麼它們就充當一種“真”和“假”指示器。
因此,當且僅當--base_size 大於--breakpoint_wide 時,我們想要一個值為1px 的變量。否則,我們想要0px。這可以使用clamp()
來完成:
<code>--is_wide: clamp(0px, var(--base_size) - var(--breakpoint_wide), 1px );</code>
如果var(--base_size) - var(--breakpoint_wide)
為負數,則--base_size 小於--breakpoint_wide,因此clamp()
在這種情況下將返回0px。
相反,如果--base_size 大於--breakpoint_wide,則計算將給出正長度,該長度大於或等於1px。這意味著clamp()
將返回1px。
bingo!我們得到了一個“寬”的指示器變量。
讓我們為“中等”區間執行此操作:
<code>--is_medium: clamp(0px, var(--base_size) - var(--breakpoint_medium), 1px ); /* 不要使用,见下文! */</code>
這將為小區間提供0px,但為中等和寬區間提供1px。然而,我們想要的是寬區間為0px,而中等區間僅為1px。
我們可以通過減去--is_wide 值來解決這個問題。在寬區間中,1px - 1px 為0px;在中等區間中,1px - 0px 為1px;對於小區間,0px - 0px 給出0px。完美。
所以我們得到:
<code>--is_medium: calc( clamp(0px, var(--base_size) - var(--breakpoint_medium), 1px) - var(--is_wide) );</code>
明白了嗎?要計算指示器變量,請使用clamp()
,其中0px 和1px 作為邊界,而--base_width 和--breakpoint_whatever 的差作為受限值。然後減去所有較大區間指示器的總和。對於最小區間指示器,此邏輯產生以下結果:
<code>--is_small: calc( clamp(0px, (var(--base_size) - 0px, 1px) - (var(--is_medium) var(--is_wide)) );</code>
我們可以跳過這裡的clamp()
,因為小區間的斷點為0px,而--base_size 為正數,因此--base_size - 0px 始終大於1px, clamp()
將始終返回1px。因此,--is_small 的計算可以簡化為:
<code>--is_small: calc(1px - (var(--is_medium) var(--is_wide)));</code>
步驟3:使用指示器變量選擇區間值
現在我們需要從這些“指示器變量”轉向一些有用的東西。讓我們假設我們正在使用基於像素的佈局。別擔心,我們稍後會處理其他單位。
這是一個問題。這返回什麼?
<code>calc(var(--is_small) * 100);</code>
如果--is_small 為1px,它將返回100px;如果--is_small 為0px,它將返回0px。
這有什麼用?看看這個:
<code>calc( (var(--is_small) * 100) (var(--is_medium) * 200) );</code>
這將在小區間(其中--is_small 為1px,--is_medium 為0px)返回100px 0px = 100px。在中等區間(其中--is_medium 為1px,--is_small 為0px)中,它將返回0px 200px = 200px。
明白了嗎?請參閱Roman Komarov 的文章,以更深入地了解這裡發生了什麼,因為它可能難以理解。
你將一個像素值(無單位)乘以相應的指示器變量,並將所有這些項加起來。因此,對於基於像素的佈局,類似這樣的東西就足夠了:
<code>width: calc( (var(--is_small) * 100) (var(--is_medium) * 200) (var(--is_wide) * 500) );</code>
但是大多數時候,我們不想要基於像素的值。我們想要概念,例如“全寬”或“三分之一寬”,甚至可能是其他單位,例如2rem、65ch 等。對於這些,我們必須繼續進行。
步驟4:使用min()
和一個極大的整數來選擇任意長度的值
在第一步中,我們定義了類似這樣的內容,而不是靜態像素值:
<code>--length_4_medium: calc((100% / 2) - 10px);</code>
那麼我們該如何使用它們呢? min()
函數來救援!
讓我們定義一個輔助變量:
<code>--very_big_int: 9999; /* 纯粹的无单位数字。必须大于其他地方出现的任何长度。 */</code>
將此值乘以指示器變量將給出0px 或9999px。此值應有多大取決於你的瀏覽器。 Chrome 將接受999999,但Firefox 不會接受這麼大的數字,因此9999 是一個在兩者中都能工作的數值。周圍幾乎沒有大於9999px 的視口,所以我們應該沒問題。
那麼,當我們將它與小於9999px 但大於0px 的任何值一起使用min()
時會發生什麼?
<code>min( var(--length_4_small), var(--is_small) * var(--very_big_int) );</code>
當且僅當--is_small 為0px 時,它將返回0px。如果--is_small 為1px,則乘法將返回9999px(大於--length_4_small),而min
將返回:--length_4_small。
這就是我們可以根據指示器變量選擇任何長度(即小於9999px 但大於0px)的方法。
如果你處理的視口大於9999px,那麼你需要調整--very_big_int 變量。這有點難看,但是一旦純CSS 可以刪除值中的單位以擺脫指示器變量中的單位(並直接將其乘以任何長度),我們就可以修復這個問題。目前,這有效。
我們現在將組合所有部分並讓烏鴉飛翔!
步驟5:將所有內容整合在一起
我們現在可以像這樣計算我們基於動態容器寬度、基於斷點的值:
<code>--dyn_length: calc( min(var(--is_wide) * var(--very_big_int), var(--length_4_wide)) min(var(--is_medium) * var(--very_big_int), var(--length_4_medium)) min(var(--is_small) * var(--very_big_int), var(--length_4_small)) );</code>
每一行都是步驟4 中的min()
。所有行都像步驟3 中那樣加起來,指示器變量來自步驟2,所有這些都基於我們在步驟1 中進行的配置——它們在一個大公式中一起工作!
想試試嗎?這是一個可以使用的Pen(請參閱CSS 中的註釋)。
這個Pen 不使用flexbox、grid 或浮動。只是一些div。這是為了表明在這種佈局中輔助程序是不必要的。但是,隨意將烏鴉與這些佈局一起使用,因為它將幫助你創建更複雜的佈局。
其他?
到目前為止,我們已經使用固定像素值作為斷點,但是如果容器大於或小於視口的一半減去10px,我們是否想要更改佈局?沒問題:
<code>--breakpoint_wide: calc(50vw - 10px);</code>
這有效!其他公式也適用。為了避免奇怪的行為,我們想要使用類似:
<code>--breakpoint_medium: min(var(--breakpoint_wide), 500px);</code>
……在500px 寬度處設置第二個斷點。步驟2 中的計算取決於--breakpoint_wide 不小於--breakpoint_medium 的事實。只需按正確的順序保持斷點: min()
和/或max()
在這裡非常有用!
高度呢?
所有計算的評估都是延遲執行的。也就是說,當將--dyn_length 分配給任何屬性時,計算將基於此位置中--base_size 的計算結果。因此,如果--base_size 為100%,則設置高度將基於100% 的高度。
我還沒有找到一種基於容器寬度設置高度的方法。因此,你可以使用padding-top
,因為100% 對填充而言相當於寬度。
顯示和隱藏內容呢?
使用烏鴉技巧顯示和隱藏內容最簡單的方法是在適當的指示器變量處將寬度設置為100px(或任何其他合適的寬度):
<code>.show_if_small { width: calc(var(--is_small) * 100); } .show_if_medium { width: calc(var(--is_medium) * 100); } .show_if_wide { width: calc(var(--is_wide) * 100); }</code>
你需要設置:
<code>overflow: hidden; display: inline-block; /* 避免难看的空行*/</code>
……或其他一些方法來隱藏寬度為0px 的框中的內容。完全隱藏框需要將其他框模型屬性(包括邊距、填充和邊框寬度)設置為0px。烏鴉可以對某些屬性執行此操作,但將其修復為0px 同樣有效。
另一種方法是使用position: absolute;
並通過left: calc(var(--is_???) * 9999);
將元素繪製到屏幕外。
關鍵點
我們可能根本不需要JavaScript,即使對於容器查詢行為也是如此!當然,我們希望如果我們在CSS 語法中實際獲得容器查詢,它將更容易使用和理解——但今天在CSS 中能夠實現這些事情也非常酷。
在處理此問題時,我對CSS 可以使用的其他內容產生了一些看法:
- 基於容器的單位,如conW 和conH,用於基於寬度設置高度。這些單位可以基於當前堆疊上下文的根元素。
- 某種“評估為值”函數,以克服延遲評估的問題。這將與在渲染時工作的“去除單位”函數一起非常有效。
注意:在早期版本中,我使用了cw 和ch 作為單位,但有人指出這些很容易與同名CSS 單位混淆。感謝評論中的Mikko Tapionlinna 和Gilson Nunes Filho 提供的提示! )
如果我們有第二個,它將允許我們使用烏鴉設置顏色(以乾淨的方式)、邊框、盒陰影、flex-grow、背景位置、z-index、scale() 和其他內容。
結合基於組件的單位,甚至可以將子尺寸設置為與父級相同的縱橫比。無法除以帶單位的值;否則--indicator / 1px 將作為烏鴉的“去除單位”工作。
附加內容:布爾邏輯
指示器變量看起來像布爾值,對吧?唯一的區別是它們有一個“px”單位。那麼這些的邏輯組合呢?想像一下諸如“容器寬度大於屏幕的一半”和“佈局處於兩列模式”之類的內容。 CSS 函數再次來救援!
對於OR 運算符,我們可以對所有指示器使用max()
:
<code>--a_OR_b: max( var(--indicator_a) , var(--indicator_b) );</code>
對於NOT 運算符,我們可以從1px 中減去指示器:
<code>--NOT_a: calc(1px - var(--indicator_a));</code>
邏輯純粹主義者可能會停在這裡,因為NOR(a,b) = NOT(OR(a,b)) 是完整的布爾代數。但是,嘿,只是為了好玩,這裡還有一些:
AND:
<code>--a_AND_b: min(var(--indicator_a), var(--indicator_b));</code>
當且僅當兩個指示器都為1px 時,這將評估為1px。
請注意, min()
和max()
接受兩個以上的參數。它們仍然作為(兩個以上)指示器變量的AND 和OR 工作。
XOR:
<code>--a_XOR_b: max( var(--indicator_a) - var(--indicator_b), var(--indicator_b) - var(--indicator_a) );</code>
如果(且僅當)兩個指示器具有相同的值時,兩個差值都為0px, max()
將返回此值。如果指示器具有不同的值,則一個項將給出-1px,另一個將給出1px。在這種情況下, max()
返回1px。
如果有人對兩個指示器相等的情況感興趣,請使用以下方法:
<code>--a_EQ_b: calc(1px - max( var(--indicator_a) - var(--indicator_b), var(--indicator_b) - var(--indicator_a) ) );</code>
是的,這是NOT(a XOR b) .我無法找到對此的“更好”的解決方案。
相等性可能對一般的CSS 長度變量更有趣,而不僅僅是用於指示器變量。通過再次使用clamp()
,這可能會有所幫助:
<code>--a_EQUALS_b_general: calc( 1px - clamp(0px, max( var(--var_a) - var(--var_b), var(--var_b) - var(--var_a) ), 1px) );</code>
刪除px 單位以獲得無單位變量(整數)的一般相等性。
我認為這對於大多數佈局來說已經足夠布爾邏輯了!
附加內容2:在網格佈局中設置列數
由於烏鴉僅限於返回CSS 長度值,因此它無法直接為網格選擇列數(因為這是一個沒有單位的值)。但是有一種方法可以使其工作(假設我們像上面那樣聲明了指示器變量):
<code>--number_of_cols_4_wide: 4; --number_of_cols_4_medium: 2; --number_of_cols_4_small: 1; --grid_gap: 0px; --grid_columns_width_4_wide: calc( (100% - (var(--number_of_cols_4_wide) - 1) * var(--grid_gap) ) / var(--number_of_cols_4_wide)); --grid_columns_width_4_medium: calc( (100% - (var(--number_of_cols_4_medium) - 1) * var(--grid_gap) ) / var(--number_of_cols_4_medium)); --grid_columns_width_4_small: calc( (100% - (var(--number_of_cols_4_small) - 1) * var(--grid_gap) ) / var(--number_of_cols_4_small)); --raven_grid_columns_width: calc( /* 使用乌鸦组合值*/ min(var(--is_wide) * var(--very_big_int),var(--grid_columns_width_4_wide)) min(var(--is_medium) * var(--very_big_int),var(--grid_columns_width_4_medium)) min(var(--is_small) * var(--very_big_int),var(--grid_columns_width_4_small)) );</code>
並使用以下方法設置你的網格:
<code>.grid_container{ display: grid; grid-template-columns: repeat(auto-fit, var(--raven_grid_columns_width)); gap: var(--grid_gap) };</code>
這是如何工作的?
- 為每個區間定義我們想要的列數(第1、2、3 行)
- 計算每個區間的完美列寬(第5、6、7 行)。這裡發生了什麼?
首先,我們計算列的可用空間。這是100%,減去間隙將佔據的空間。對於n 列,有(n-1) 個間隙。然後將此空間除以我們想要的列數。 3. 使用烏鴉計算實際--base_size 的正確列寬。
在網格容器中,此行:
<code>grid-template-columns: repeat(auto-fit, var(--raven_grid_columns_width));</code>
……然後選擇列數以適應烏鴉提供的值(這將導致我們上面的--number_of_cols 4 ??? 變量)。
烏鴉可能無法直接給出列數,但它可以給出長度,使repeat
和autofit
為我們計算我們想要的數字。
但是auto-fit
與minmax()
做同樣的事情,對吧?不!上面的解決方案永遠不會給出三列(或五列),並且列數不需要隨著容器的寬度而增加。嘗試在此Pen 中設置以下值以查看烏鴉全力飛行:
<code>--number_of_cols_4_wide: 1; --number_of_cols_4_medium: 2; --number_of_cols_4_small: 4;</code>
附加內容3:使用linear-gradient()
更改背景顏色
這個有點更費腦筋。烏鴉完全是關於長度值的,那麼我們如何從這些值中獲得顏色呢?好吧,線性漸變同時處理兩者。它們在由長度值定義的特定區域中定義顏色。讓我們在進入代碼之前更詳細地討論這個概念。
為了解決實際的漸變部分,一個眾所周知的技術是將顏色停止點加倍,有效地使漸變部分在0px 內發生。查看此代碼以了解如何執行此操作:
<code>background-image:linear-gradient( to right, red 0%, red 50%, blue 50%, blue 100% );</code>
這將使你的背景左側一半為紅色,右側為藍色。注意第一個參數“to right”。這意味著百分比值是從左到右水平評估的。
通過烏鴉變量控制50% 的值允許隨意移動顏色停止點。我們可以添加更多顏色停止點。在運行示例中,我們需要三種顏色,從而產生兩個(加倍的)內部顏色停止點。
添加一些顏色和顏色停止點的變量,這就是我們得到的:
<code>background-image: linear-gradient( to right, var(--color_small) 0px, var(--color_small) var(--first_lgbreak_value), var(--color_medium) var(--first_lgbreak_value), var(--color_medium) var(--second_lgbreak_value), var(--color_wide) var(--second_lgbreak_value), var(--color_wide) 100% );</code>
但是我們如何計算--first_lgbreak_value 和--second_lgbreak_value 的值呢?讓我們看看。
第一個值控制--color_small 的可見位置。在小區間中,它應該是100%,在其他區間中應該是0px。我們已經了解瞭如何使用烏鴉做到這一點。第二個變量控制--color_medium 的可見性。對於小區間,它應該是100%;對於中等區間,它應該是100%;但對於寬區間,它應該是0px。如果容器寬度位於小或中等區間,則相應的指示器必須為1px。
由於我們可以對指示器進行布爾邏輯運算,因此它是:
<code>max(--is_small, --is_medium)</code>
……來獲取正確的指示器。這給出:
<code>--first_lgbreak_value: min(var(--is_small) * var(--very_big_int), 100%); --second_lgbreak_value: min( max(var(--is_small), var(--is_medium)) * var(--very_big_int), 100%);</code>
將所有內容放在一起會產生以下CSS 代碼,該代碼會根據寬度更改背景顏色(區間指示器如上所示計算):
<code>--first_lgbreak_value: min( var(--is_small) * var(--very_big_int), 100%); --second_lgbreak_value: min( max(var(--is_small), var(--is_medium)) * var(--very_big_int), 100%); --color_wide: red;/* 根据你的需求更改*/ --color_medium: green;/* 根据你的需求更改*/ --color_small: lightblue;/* 根据你的需求更改*/ background-image: linear-gradient( to right, var(--color_small) 0px, var(--color_small) var(--first_lgbreak_value), var(--color_medium) var(--first_lgbreak_value), var(--color_medium) var(--second_lgbreak_value), var(--color_wide) var(--second_lgbreak_value), var(--color_wide) 100% );</code>
這是一個可以查看其運行情況的Pen。
附加內容4:擺脫嵌套變量
在使用烏鴉時,我遇到一個奇怪的問題: calc()
中可以使用嵌套變量的數量有限.當使用太多斷點時,這可能會導致一些問題。據我了解,此限制是為了防止在計算樣式時阻塞頁面並允許更快地進行循環引用檢查。
在我看來,“評估為值”之類的東西將是克服這個問題的好方法。然而,這個限制在突破CSS 的限制時可能會讓你頭疼。希望這個問題將來能夠得到解決。
有一種方法可以計算烏鴉的指示器變量,而無需使用(深度)嵌套變量。讓我們看看--is_medium 值的原始計算:
<code>--is_medium:calc( clamp(0px, var(--base_size) - var(--breakpoint_medium), 1px) - var(--is_wide) );</code>
問題出現在減去--is_wide 的地方。這會導致CSS 解析器粘貼--is_wide 的完整公式的定義。 --is_small 的計算甚至有更多此類引用。 (--is_wide 的定義甚至會被粘貼兩次,因為它隱藏在--is_medium 的定義中,並且也直接使用。)
幸運的是,有一種方法可以計算指示器,而無需引用較大斷點的指示器。
當且僅當--base_size 大於區間的下限斷點且小於或等於區間的上限斷點時,指示器才為真。此定義為我們提供了以下代碼:
<code>--is_medium: min( clamp(0px, var(--base_size) - var(--breakpoint_medium), 1px), clamp(0px, 1px var(--breakpoint_wide) - var(--base_size), 1px) );</code>
-
min()
用作邏輯AND 運算符 - 第一個
clamp()
是“--base_size 大於--breakpoint_medium” - 第二個
clamp()
表示“--base_size 小於或等於--breakpoint_wide。” - 添加1px 將從“小於”切換到“小於或等於”。這有效,因為我們正在處理整數(像素)數字(a
指示器變量的完整計算可以通過這種方式完成:
<code>--is_wide: clamp(0px, var(--base_size) - var(--breakpoint_wide), 1px); --is_medium: min(clamp(0px, var(--base_size) - var(--breakpoint_medium), 1px), clamp(0px, 1px var(--breakpoint_wide) - var(--base_size), 1px) ); --is_small: clamp(0px,1px var(--breakpoint_medium) - var(--base_size), 1px);</code>
--is_wide 和--is_small 的計算更簡單,因為每個只需要檢查一個給定的斷點。
這適用於我們到目前為止所看到的所有內容。這是一個結合示例的Pen。
最後的想法
烏鴉無法完成媒體查詢可以完成的所有事情。但我們不需要它那樣做,因為我們在CSS 中有媒體查詢。對於“大型”設計更改(例如側邊欄的位置或菜單的重新配置),使用它們是可以的。這些事情發生在整個視口(瀏覽器窗口的大小)的上下文中。
但是對於組件而言,媒體查詢有點錯誤,因為我們永遠不知道組件的大小。
Heydon Pickering 使用此圖像演示了此問題:
我希望烏鴉能夠幫助你克服為組件創建響應式佈局的問題,並將“CSS 可以做什麼”的限制進一步推高。
通過展示今天可能實現的功能,也許可以通過添加一些語法糖和一些非常小的新函數(如conW、conH、“去除單位”或“評估為像素”)來完成“真正的”容器查詢。如果CSS 中有一個函數允許將“1px”重寫為空格,而將“0px”重寫為“initial”,則烏鴉可以與自定義屬性切換技巧結合使用並更改每個CSS 屬性,而不僅僅是長度值。
通過避免使用JavaScript 來實現這一點,你的佈局渲染速度會更快,因為它不依賴於JavaScript 的下載或運行。即使禁用了JavaScript 也不重要。這些計算不會阻塞你的主線程,並且你的應用程序邏輯不會因設計邏輯而混亂。
感謝Chris、Andrés Galante、Cathy Dutton、Marko Ilic 和David Atanda 的精彩CSS-Tricks 文章。它們確實幫助我探索了烏鴉可以實現的功能。
以上是烏鴉技術:距離容器查詢更近一步的詳細內容。更多資訊請關注PHP中文網其他相關文章!

對於Astro,我們可以在構建過程中生成大部分網站,但是有一小部分服務器端代碼可以使用Fuse.js之類的搜索功能來處理搜索功能。在此演示中,我們將使用保險絲搜索一組個人“書籤”


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

SublimeText3 Linux新版
SublimeText3 Linux最新版

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1
強大的PHP整合開發環境

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。