目錄
HTML結構
創建粘性元素
方案一:偽元素
方案二:填充計算
首頁 web前端 css教學 如何獲得粘性和全溢的元素來很好地發揮作用

如何獲得粘性和全溢的元素來很好地發揮作用

Apr 01, 2025 am 12:46 AM

How to Get Sticky and Full-Bleed Elements to Play Well Together

最近我遇到一個獨特的佈局需求:在頁麵包含全屏元素的同時,保持一個元素始終固定在頂部。這實現起來相當棘手,因此我將記錄下我的解決方案,以備不時之需。尤其是在小屏幕上的邏輯定位處理上,更是增加了難度。

效果難以用文字描述,所以我錄製了屏幕視頻來說明我的意思。請特別注意主要的號召性用語部分,也就是帶有“立即體驗Domino”標題的部分。

我們的目標是在較大視窗中,將主要的號召性用語顯示在右側,而用戶向下滾動時,其他部分會從其下方經過。在較小視窗中,號召性用語元素必須顯示在帶有“開始試用”標題的主要英雄區之後。

這裡主要有兩個挑戰:

  • 創建不與粘性元素衝突的全屏元素
  • 避免重複HTML代碼

在深入探討幾種可能的解決方案(及其局限性)之前,讓我們先搭建語義化的HTML結構。

HTML結構

構建此類佈局時,可能會傾向於創建重複的號召性用語部分:一個用於桌面版本,另一個用於移動版本,然後在適當的時候切換它們的可見性。這避免了在HTML中尋找完美位置以及應用處理兩種佈局需求的CSS的麻煩。我必須承認,我有時也會這樣做。但這一次,我想避免重複我的HTML代碼。

另一個需要考慮的是,我們對.box--sticky元素使用了粘性定位,這意味著它需要與其他元素(包括全屏元素)同級,才能正常工作。

以下是標記:

<div>

  <div>英雄區</div>

  <div>粘性區</div>

  <div>全屏區</div>
  <div>全屏區</div>


</div>
登入後複製

創建粘性元素

在CSS網格佈局中創建粘性元素非常簡單。我們向.box--sticky元素添加position: stickytop: 0偏移量,指示其開始粘貼的位置。注意,我們只在視窗寬度大於768px時才使元素粘性化。

 @media screen and (min-width: 768px) {
  .box--sticky {
    position: sticky;
    top: 0;
  }
}
登入後複製

需要注意的是,當position: stickyoverflow: auto一起使用時,Safari中存在已知的粘性定位問題。 Caniuse網站的已知問題部分對此進行了說明:

設置為overflow: auto的父元素會阻止Safari中position: sticky的工作。

不錯,這很容易。接下來讓我們解決全屏元素的挑戰。

方案一:偽元素

第一個方案是我經常使用的方法:絕對定位的偽元素,可以從一側延伸到另一側。這裡的技巧是使用負偏移量。

如果我們討論的是居中內容,那麼計算就相當簡單:

 .box--bleed {
  max-width: 600px;
  margin-right: auto;
  margin-left: auto;
  padding: 20px;
  position: relative; 
}

.box--bleed::before {
  content: "";
  background-color: dodgerblue; 
  position: absolute;
  top: 0;
  bottom: 0;
  right: calc((100vw - 100%) / -2);
  left: calc((100vw - 100%) / -2);
}
登入後複製

簡而言之,負偏移量是視窗寬度( 100vw )減去元素寬度( 100% ),然後除以-2,因為我們需要兩個負偏移量。

需要注意的是,使用100vw時存在一個已知的bug,Caniuse網站也對此進行了說明:

目前除Firefox之外的所有瀏覽器都錯誤地認為100vw是整個頁面寬度,包括垂直滾動條,當設置overflow: auto時,這可能會導致水平滾動條。

現在讓我們在內容居中的情況下創建全屏元素。如果你再次觀看視頻,你會注意到粘性元素下方沒有內容。我們不希望粘性元素與內容重疊,這就是為什麼在這個特定的佈局中沒有居中內容的原因。

首先,我們將創建網格:

 .grid {
  display: grid;
  grid-gap: var(--gap);
  grid-template-columns: var(--cols);
  max-width: var(--max-width);
  margin-left: auto;
  margin-right: auto;
}
登入後複製

我們使用自定義屬性,允許我們重新定義最大寬度、間隙和網格列,而無需重新聲明屬性。換句話說,我們重新聲明變量值,而不是重新聲明grid-gapgrid-template-columnsmax-width屬性:

 :root {
  --gap: 20px;
  --cols: 1fr;
  --max-width: calc(100% - 2 * var(--gap));
}

@media screen and (min-width: 768px) {
  :root {
    --max-width: 600px;
    --aside-width: 200px;
    --cols: 1fr var(--aside-width);
  }
}

@media screen and (min-width: 980px) {
  :root {
    --max-width: 900px;
    --aside-width: 300px;
  }
}
登入後複製

在寬度為768px及以上的視窗上,我們定義了兩列:一列具有固定寬度( --aside-width ),另一列填充剩餘空間( 1fr ),以及網格容器的最大寬度( --max-width width )。

在小於768px的視窗上,我們定義了一列和間隙。網格容器的最大寬度是視窗的100%,減去兩側的間隙。

現在是精彩的部分。內容在較大的視窗上沒有居中,因此計算不像你想像的那麼簡單。以下是它的樣子:

 .box--bleed {
  position: relative;
  z-index: 0;
}

.box--bleed::before {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc((100vw - (100% var(--gap) var(--aside-width))) / -2);
  right: calc(((100vw - (100% - var(--gap) var(--aside-width))) / -2) - (var(--aside-width)));
  z-index: -1;
}
登入後複製

我們沒有使用父元素寬度的100%,而是考慮了間隙和粘性元素的寬度。這意味著全屏元素中的內容寬度不會超過英雄元素的邊界。這樣,我們確保粘性元素不會與任何重要信息重疊。

左側偏移量比較簡單,因為我們只需要從視窗寬度( 100vw )中減去元素寬度( 100% )、間隙( --gap )和粘性元素( --aside-width )。

 left: (100vw - (100% var(--gap) var(--aside-width))) / -2);
登入後複製

右側偏移量比較複雜,因為我們必須將粘性元素的寬度添加到之前的計算中, --aside-width ,以及間隙, --gap

 right: ((100vw - (100% var(--gap) var(--aside-width))) / -2) - (var(--aside-width) var(--gap));
登入後複製

現在我們可以確保粘性元素不會與全屏元素中的任何內容重疊。

這是一個包含水平bug的解決方案:

這是一個包含水平bug修復的解決方案:

修復方法是隱藏body的x軸溢出,這通常也是一個好主意:

 body {
  max-width: 100%;
  overflow-x: hidden;
}
登入後複製

這是一個完全可行的解決方案,我們可以在此結束。但這有什麼樂趣呢?通常不止一種方法可以完成某件事,所以讓我們看看另一種方法。

方案二:填充計算

我們可以通過配置網格來實現相同的效果,而不是使用居中的網格容器和偽元素。讓我們從定義網格開始,就像我們上次做的那樣:

 .grid {
  display: grid;
  grid-gap: var(--gap);
  grid-template-columns: var(--cols);
}
登入後複製

同樣,我們使用自定義屬性來定義間隙和模板列:

 :root {
  --gap: 20px;
  --gutter: 1px;
  --cols: var(--gutter) 1fr var(--gutter);
}
登入後複製

我們在小於768px的視窗上顯示三列。中間列佔據盡可能多的空間,而另外兩列僅用於強制水平間隙。

 @media screen and (max-width: 767px) {
  .box {
    grid-column: 2 / -2;
  }
}
登入後複製

請注意,所有網格元素都放置在中間列中。

在大於768px的視窗上,我們定義了一個--max-width變量,它限制了內部列的寬度。我們還定義了--aside-width ,即粘性元素的寬度。同樣,這樣可以確保粘性元素不會定位在全屏元素內的任何內容之上。

 :root {
  --gap: 20px;
}

@media screen and (min-width: 768px) {
  :root {
    --max-width: 600px;
    --aside-width: 200px;
    --gutter: calc((100% - (var(--max-width))) / 2 - var(--gap));
    --cols: var(--gutter) 1fr var(--aside-width) var(--gutter);
  }
}

@media screen and (min-width: 980px) {
  :root {
    --max-width: 900px;
    --aside-width: 300px;
  }
}
登入後複製

接下來,我們將計算邊距寬度。計算公式是:

 --gutter: calc((100% - (var(--max-width))) / 2 - var(--gap));
登入後複製

…其中100%是視窗寬度。首先,我們從視窗寬度中減去內部列的最大寬度。然後,我們將結果除以2以創建邊距。最後,我們減去網格間隙以獲得邊距列的正確寬度。

現在讓我們將.box--hero元素推到一邊,以便它從網格的第一列開始:

 @media screen and (min-width: 768px) {
  .box--hero {
    grid-column-start: 2;
  }
}
登入後複製

這會自動推動粘性框,使其緊跟在英雄元素之後。我們也可以明確地定義粘性框的位置,如下所示:

 .box--sticky {
  grid-column: 3 / span 1;
}
登入後複製

最後,讓我們通過將grid-column設置為1 / -1來創建全屏元素。這告訴元素從第一個網格項開始內容,並跨越到最後一個網格項。

 @media screen and (min-width: 768px) {  
  .box--bleed {
    grid-column: 1 / -1;
  }
}
登入後複製

為了居中內容,我們將計算左側和右側填充。左側填充等於邊距列的大小加上網格間隙。右側填充等於左側填充的大小,再加上另一個網格間隙以及粘性元素的寬度。

 @media screen and (min-width: 768px) {
  .box--bleed {  
    padding-left: calc(var(--gutter) var(--gap));
    padding-right: calc(var(--gutter) var(--gap) var(--gap) var(--aside-width));
  }
}
登入後複製

這是最終的解決方案:

我更喜歡這個解決方案,因為它沒有使用有問題的視窗單位。

我喜歡CSS計算。使用數學運算並不總是直截了當的,尤其是在組合不同的單位時,例如100% 。弄清楚100%的含義是工作的一半。

我也喜歡使用CSS解決簡單但複雜的佈局,就像這個一樣。現代CSS具有原生解決方案——例如網格、粘性定位和計算——消除了複雜且相當繁重的JavaScript解決方案。讓我們把臟活留給瀏覽器吧!

你對此有更好的解決方案或不同的方法嗎?我很樂意聽到你的想法。

以上是如何獲得粘性和全溢的元素來很好地發揮作用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1660
14
CakePHP 教程
1417
52
Laravel 教程
1311
25
PHP教程
1261
29
C# 教程
1234
24
Google字體可變字體 Google字體可變字體 Apr 09, 2025 am 10:42 AM

我看到Google字體推出了新設計(Tweet)。與上一次大型重新設計相比,這感覺更加迭代。我幾乎無法分辨出區別

如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 Apr 11, 2025 am 11:29 AM

您是否曾經在項目上需要一個倒計時計時器?對於這樣的東西,可以自然訪問插件,但實際上更多

HTML數據屬性指南 HTML數據屬性指南 Apr 11, 2025 am 11:50 AM

您想了解的有關HTML,CSS和JavaScript中數據屬性的所有信息。

使Sass更快的概念證明 使Sass更快的概念證明 Apr 16, 2025 am 10:38 AM

在一個新項目開始時,Sass彙編發生在眼睛的眨眼中。感覺很棒,尤其是當它與browsersync配對時,它重新加載

我們如何創建一個在SVG中生成格子呢模式的靜態站點 我們如何創建一個在SVG中生成格子呢模式的靜態站點 Apr 09, 2025 am 11:29 AM

格子呢是一塊圖案布,通常與蘇格蘭有關,尤其是他們時尚的蘇格蘭語。在Tar​​tanify.com上,我們收集了5,000多個格子呢

如何在WordPress主題中構建VUE組件 如何在WordPress主題中構建VUE組件 Apr 11, 2025 am 11:03 AM

內聯式模板指令使我們能夠將豐富的VUE組件構建為對現有WordPress標記的逐步增強。

php是A-OK用於模板 php是A-OK用於模板 Apr 11, 2025 am 11:04 AM

PHP模板通常會因促進Subpar代碼而變得不良說唱,但這並不是這樣的情況。讓我們看一下PHP項目如何執行基本的

編程SASS創建可訪問的顏色組合 編程SASS創建可訪問的顏色組合 Apr 09, 2025 am 11:30 AM

我們一直在尋求使網絡更容易訪問。顏色對比只是數學,因此Sass可以幫助涵蓋設計師可能錯過的邊緣案例。

See all articles