」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 幾次容器尺寸查詢會幫助我

幾次容器尺寸查詢會幫助我

發佈於2025-03-24
瀏覽:387

A Few Times Container Size Queries Would Have Helped Me Out

CSS 容器查询技术日渐成熟,许多开发者开始尝试应用于各种项目,即使只是简单的实验。虽然浏览器支持度并非完全普及,但在某些项目中已足够实用,但可能还不足以完全取代旧项目中的媒体查询。

容器查询确实非常方便!事实上,我已经遇到过几次情况,非常希望用到它,但却受限于浏览器兼容性。如果当时可以使用容器查询,效果将会更好。

以下所有演示在撰写本文时,最好在 Chrome 或 Safari 中查看。Firefox 计划在 109 版本中提供支持。

案例一:卡片网格

这个案例大家应该都比较熟悉,对吧?这是一个非常常见的模式,我们几乎都会遇到。但事实是,如果可以使用容器查询而不是标准媒体查询,将会节省大量时间,并获得更好的结果。

假设您需要构建一个卡片网格,要求每个卡片保持 1:1 的纵横比:

这比看起来要难!问题在于,根据视口宽度调整组件内容大小,会让您受制于组件对视口的响应方式,以及任何其他祖先容器对视口的响应方式。例如,如果您希望当卡片达到特定内联大小时,卡片标题的字体大小减小,则没有可靠的方法可以做到这一点。

您可以使用 vw 单位设置字体大小,但是组件仍然与浏览器的视口宽度绑定。当卡片网格在其他可能没有相同断点的上下文中使用时,这可能会导致问题。

在我的实际项目中,我采用了 JavaScript 方法:

  1. 监听调整大小事件。
  2. 计算每个卡片的宽度。
  3. 根据卡片宽度添加内联字体大小。
  4. 使用 em 单位设置内部样式。

看起来工作量很大,对吧?但这是一个稳定的解决方案,可以在不同屏幕尺寸和不同上下文中实现所需的缩放。

容器查询将会更好,因为它提供了容器查询单位,例如 cqw 单位。您可能已经了解,1cqw 等于容器宽度的 1%。我们还有 cqi 单位,它是容器内联宽度的度量,cqb 用于容器块宽度。因此,如果我们有一个 500px 宽的卡片容器,则 50cqw 的值计算为 250px。

如果在我的卡片网格中可以使用容器查询,我可以将 .card 组件设置为容器:

.card { 
  container: card / size;
}

然后,我可以使用 cqw 单位设置一个具有填充的内部包装器,该包装器按 .card 宽度的 10% 缩放:

.card__inner { 
  padding: 10cqw; 
} 

这是一种不错的方法,可以一致地缩放卡片边缘与其内容之间的间距,无论卡片在任何给定视口宽度下在何处使用。无需媒体查询!

另一个想法?使用 cqw 单位作为内部内容的字体大小,然后使用 em 单位应用填充:

.card__inner { 
  font-size: 5cqw; 
  padding: 2em;
} 

5cqw 是一个任意值——我只是选择了一个值。该填充仍然等于 10cqw,因为 em 单位相对于 .card__inner 字体大小!

您注意到了吗?2em 相对于在同一容器上设置的 5cqw 字体大小!容器的工作方式与我们习惯的不同,因为 em 单位相对于同一元素的字体大小值。但我很快注意到,容器查询单位与最近的父级(也是容器)相关。

例如,在这个例子中,5cqw 不会根据 .card 元素的宽度缩放:

.card { 
  container: card / size; 
  container-name: card; 
  font-size: 5cqw; 
}

相反,它会缩放至定义为容器的最近父级。这就是为什么我设置了一个 .card__inner 包装器。

案例二:交替布局

在另一个项目中,我还需要另一个卡片组件。这次,我需要卡片在屏幕变小时从横向布局过渡到纵向布局……然后再次回到横向布局,再回到纵向布局。

我完成了这项艰巨的工作,使该组件在两个特定的视口范围内变为纵向(向新的媒体查询范围语法致敬!),但问题是它随后被锁定在对其、其父级以及可能响应视口宽度的任何其他内容设置的媒体查询上。我们需要一种在任何情况下都能工作的东西,而不用担心内容将在哪里中断!

由于使用了 @container 规则,容器查询可以轻松解决这个问题:

.info-card {
  container-type: inline-size;
  container-name: info-card;
}

@container info-card (max-width: 500px) {
  .info-card__inner {
    flex-direction: column;
  }
}

一个查询,无限流畅:

但是等等!您可能需要注意一些问题。具体来说,在基于 prop 的设计系统中使用这样的容器查询可能很困难。例如,此 .info-card 组件可能包含依赖于 prop 来更改其外观的子组件。

为什么这很重要?卡片的纵向布局可能需要备用样式,但您无法使用 CSS 更改 JavaScript prop。因此,您可能会重复所需的样式。我在另一篇文章中实际讨论了这一点以及如何解决这个问题。如果您需要将容器查询用于大量样式,那么您可能需要围绕它们构建整个设计系统,而不是试图将它们塞入一个依赖媒体查询的现有设计系统中。

案例三:SVG 描边

这是我最近使用过的另一个非常常见的模式,如果使用容器查询,将会得到更完善的产品。假设您有一个与标题锁定的图标:

Heading

即使没有媒体查询,也很容易根据标题的大小缩放图标。但是,问题是 SVG 的 stroke-width 在较小尺寸下可能会太细而难以注意到,而在较大尺寸下可能会过于粗而过于显眼。

我不得不为每个图标实例创建和应用类来确定其大小和描边宽度。如果图标位于使用固定字体大小的标题旁边,这还可以,但是当使用不断变化的流体类型时,效果就不那么好了。

标题的字体大小可能基于视口宽度,因此 SVG 图标需要相应地调整其描边在任何大小下都能正常工作。您可以通过使用 em 单位设置描边宽度使其相对于标题的字体大小。但是,如果您需要坚持使用一组特定的描边大小,则此方法无效,因为它会线性缩放——如果没有在视口宽度上使用媒体查询,则无法将其调整到特定描边宽度值,而不会诉诸于视口宽度上的媒体查询。

但是,如果我有机会使用容器查询,我会这样做:

.icon {
  container: icon / size; 
  width: 1em; 
  height: 1em; 
}

.icon svg {
  width: 100%; 
  height: 100%; 
  fill: none; 
  stroke: #ccc; 
  stroke-width: 0.8; 
}

@container icon (max-width: 70px) {
  .icon svg {
    stroke-width: 1.5; 
  }
}
@container icon (max-width: 35px) {
  .icon svg {
    stroke-width: 3;
  }
}

比较这些实现,看看容器查询版本如何根据容器的宽度将 SVG 的描边捕捉到我想要的特定宽度。

附加内容:其他类型的容器大小查询

好的,我实际上并没有在实际项目中遇到这种情况。但是,当我仔细研究容器查询的信息时,我注意到我们可以查询与容器大小或物理尺寸相关的容器的其他内容。

我在这篇文章中一直在使用的示例大多查询宽度、最大宽度和最小宽度、高度、块大小和内联大小。

@container info-card (max-width: 500px) {
  .info-card__inner {
    flex-direction: column;
  }
}

但是 MDN 概述了我们可以查询的另外两件事。一个是方向,这非常有意义,因为我们一直在媒体查询中使用它。容器查询也是如此:

@media screen (orientation: landscape) { 
  .info-card__inner {
    /* Style away! */
  }
} 

@container info-card (orientation: landscape) { 
  .info-card__inner {
    /* Style away! */
  }
} 

另一个是纵横比,信不信由你:

@container info-card (aspect-ratio: 3/2) { 
  .info-card__inner {
    /* Style away! */
  }
} 

这是一个可编辑的演示,可以用来试验这两个例子:

我还没有真正找到这两个的良好用例。如果您有任何想法或觉得它可以帮助您完成项目,请在评论中告诉我!

最新教學 更多>
  • 可以在純CS中將多個粘性元素彼此堆疊在一起嗎?
    可以在純CS中將多個粘性元素彼此堆疊在一起嗎?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    程式設計 發佈於2025-04-19
  • 表單刷新後如何防止重複提交?
    表單刷新後如何防止重複提交?
    在Web開發中預防重複提交 在表格提交後刷新頁面時,遇到重複提交的問題是常見的。要解決這個問題,請考慮以下方法: 想像一下具有這樣的代碼段,看起來像這樣的代碼段:)){ //數據庫操作... 迴聲“操作完成”; 死(); } ? > ...
    程式設計 發佈於2025-04-19
  • 切換到MySQLi後CodeIgniter連接MySQL數據庫失敗原因
    切換到MySQLi後CodeIgniter連接MySQL數據庫失敗原因
    Unable to Connect to MySQL Database: Troubleshooting Error MessageWhen attempting to switch from the MySQL driver to the MySQLi driver in CodeIgniter,...
    程式設計 發佈於2025-04-19
  • PHP與C++函數重載處理的區別
    PHP與C++函數重載處理的區別
    作為經驗豐富的C開發人員脫離謎題,您可能會遇到功能超載的概念。這個概念雖然在C中普遍,但在PHP中構成了獨特的挑戰。讓我們深入研究PHP功能過載的複雜性,並探索其提供的可能性。 在PHP中理解php的方法在PHP中,函數超載的概念(如C等語言)不存在。函數簽名僅由其名稱定義,而與他們的參數列表無關...
    程式設計 發佈於2025-04-19
  • PHP SimpleXML解析帶命名空間冒號的XML方法
    PHP SimpleXML解析帶命名空間冒號的XML方法
    在php 很少,請使用該限制很大,很少有很高。例如:這種技術可確保可以通過遍歷XML樹和使用兒童()方法()方法的XML樹和切換名稱空間來訪問名稱空間內的元素。
    程式設計 發佈於2025-04-19
  • 如何將來自三個MySQL表的數據組合到新表中?
    如何將來自三個MySQL表的數據組合到新表中?
    mysql:從三個表和列的新表創建新表 答案:為了實現這一目標,您可以利用一個3-way Join。 選擇p。 *,d.content作為年齡 來自人為p的人 加入d.person_id = p.id上的d的詳細信息 加入T.Id = d.detail_id的分類法 其中t.taxonomy ...
    程式設計 發佈於2025-04-19
  • 如何使用FormData()處理多個文件上傳?
    如何使用FormData()處理多個文件上傳?
    )處理多個文件輸入時,通常需要處理多個文件上傳時,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    程式設計 發佈於2025-04-19
  • 使用CSS讓兩個浮動Div高度一致的技巧
    使用CSS讓兩個浮動Div高度一致的技巧
    在html/css 使用CSS創建相等的高度divs One approach involves setting large bottom padding, negating that padding with negative bottom margin, and surrounding th...
    程式設計 發佈於2025-04-19
  • 圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    在chrome 中刪除一個頻繁的問題時,在與Chrome and IE9中的圖像一起工作時,遇到了一個頻繁的問題。和“邊境:無;”在CSS中。要解決此問題,請考慮以下方法: Chrome具有忽略“ border:none; none;”的已知錯誤,風格。要解決此問題,請使用以下CSS ID塊創建帶...
    程式設計 發佈於2025-04-19
  • Java中Lambda表達式為何需要“final”或“有效final”變量?
    Java中Lambda表達式為何需要“final”或“有效final”變量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    程式設計 發佈於2025-04-19
  • PHP陣列鍵值異常:了解07和08的好奇情況
    PHP陣列鍵值異常:了解07和08的好奇情況
    PHP數組鍵值問題,使用07&08 在給定數月的數組中,鍵值07和08呈現令人困惑的行為時,就會出現一個不尋常的問題。運行print_r($月份)返回意外結果:鍵“ 07”丟失,而鍵“ 08”分配給了9月的值。 此問題源於PHP對領先零的解釋。當一個數字帶有0(例如07或08)的前綴時,PHP...
    程式設計 發佈於2025-04-19
  • 如何將Allegro庫集成到Visual Studio項目中
    如何將Allegro庫集成到Visual Studio項目中
    將外部庫將其納入Visual Studio項目:添加Allegro 將Allegro添加到Visual Studio 確保您已經下載了Allegro庫並在系統上確定了其位置。 It typically comes in a .dll format.Project Properties Modifi...
    程式設計 發佈於2025-04-19
  • FastAPI自定義404頁面創建指南
    FastAPI自定義404頁面創建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    程式設計 發佈於2025-04-19
  • 如何在php中使用捲髮發送原始帖子請求?
    如何在php中使用捲髮發送原始帖子請求?
    如何使用php 創建請求來發送原始帖子請求,開始使用curl_init()開始初始化curl session。然後,配置以下選項: curlopt_url:請求 [要發送的原始數據指定內容類型,為原始的帖子請求指定身體的內容類型很重要。在這種情況下,它是文本/平原。要執行此操作,請使用包含以下標頭...
    程式設計 發佈於2025-04-19
  • HTML格式標籤
    HTML格式標籤
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    程式設計 發佈於2025-04-19

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3