Table of Contents
HTML structure
Create sticky elements
Solution 1: Pseudo-element
Solution 2: Fill calculation
Home Web Front-end CSS Tutorial How to Get Sticky and Full-Bleed Elements to Play Well Together

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

Apr 01, 2025 am 12:46 AM

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

Recently I encountered a unique layout requirement: keeping an element always fixed on the top while the page contains full screen elements. This is quite tricky to implement, so I will document my solution in case of any inaccurate needs. Especially in the logical positioning processing on small screens, it increases the difficulty.

The effect is difficult to describe in text, so I recorded a screen video to illustrate what I mean. Pay special attention to the main call to action section, that is, the section with the title "Experience Domino now".

Our goal is to display the main call to action on the right in a larger window, and other parts pass under it as the user scrolls down. In a smaller window, the call to action element must be displayed after the main hero area with the title "Start Trial".

There are two main challenges here:

  • Create full-screen elements that do not conflict with sticky elements
  • Avoid duplicate HTML code

Before we dive into several possible solutions (and their limitations), let's build a semantic HTML structure.

HTML structure

When building such layouts, you may tend to create duplicate call-to-action sections: one for desktop versions, the other for mobile versions, and then toggle their visibility when appropriate. This avoids the hassle of finding the perfect location in HTML and applying CSS that handles both layout requirements. I must admit that I do the same sometimes. But this time, I want to avoid duplicating my HTML code.

Another thing to consider is that we use sticky positioning for .box--sticky element, which means it needs to be at the same level as other elements (including full screen elements) in order to work properly.

The following are the markers:

<div>

  <div>Hero Zone</div>

  <div>Adhesive zone</div>

  <div>Full screen area</div>
  <div>Full screen area</div>


</div>
Copy after login

Create sticky elements

Creating sticky elements in a CSS grid layout is very simple. We add position: sticky and top: 0 offsets to .box--sticky element, indicating where it starts pasting. Note that we only make the elements sticky when the window width is greater than 768px.

 @media screen and (min-width: 768px) {
  .box--sticky {
    position: sticky;
    top: 0;
  }
}
Copy after login

It should be noted that when position: sticky is used with overflow: auto , there are known sticky positioning problems in Safari. This is explained in the Known Issues section of the Caniuse website:

Setting to overflow: auto 's parent element will prevent position: sticky in Safari from working.

Not bad, it's easy. Next, let's solve the challenge of full-screen elements.

Solution 1: Pseudo-element

The first solution is the method I often use: absolutely positioned pseudo-elements that can extend from one side to the other. The trick here is to use negative offsets.

If we are talking about centering, the calculation is quite simple:

 .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);
}
Copy after login

In short, the negative offset is the window width ( 100vw ) minus the element width ( 100% ) and then divide by -2 because we need two negative offsets.

It should be noted that there is a known bug when using 100vw , and the Caniuse website also explained this:

Currently all browsers except Firefox are mistakenly thinking that 100vw is the entire page width, including the vertical scroll bar, which can result in horizontal scroll bars when overflow: auto is set.

Now let's create full screen elements without the content being centered. If you watch the video again, you will notice that there is no content under the sticky element. We don't want sticky elements to overlap with content, which is why there is no centered content in this particular layout.

First, we will create the grid:

 .grid {
  display: grid;
  grid-gap: var(--gap);
  grid-template-columns: var(--cols);
  max-width: var(--max-width);
  margin-left: auto;
  margin-right: auto;
}
Copy after login

We use custom properties that allow us to redefine the maximum width, gap, and grid columns without redeclaring the properties. In other words, we redeclare the variable values ​​instead of redeclaring grid-gap , grid-template-columns and max-width properties:

 :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;
  }
}
Copy after login

On a window with a width of 768px and above, we define two columns: one with a fixed width ( --aside-width ), the other with a remaining space ( 1fr ), and the maximum width of the grid container ( --max-width ).

On windows less than 768px, we define a column and gap. The maximum width of the grid container is 100% of the viewport, minus the gap on both sides.

Now is the wonderful part. The content is not centered on the larger window, so the calculation is not as simple as you think. Here's what it looks like:

 .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;
}
Copy after login

Instead of using 100% of the parent element width, we consider the gap and the width of the sticky element. This means that the content width in the full screen element does not exceed the boundary of the hero element. This way, we ensure that the sticky elements do not overlap with any important information.

The left offset is relatively simple because we only need to subtract the element width ( 100% ), gap ( --gap ) and sticky elements ( --aside-width ) from the window width ( 100vw ).

 left: (100vw - (100% var(--gap) var(--aside-width)) / -2);
Copy after login

The right offset is more complicated because we have to add the width of the sticky element to the previous calculation, --aside-width , and gap, --gap :

 right: ((100vw - (100% var(--gap) var(--aside-width))) / -2) - (var(--aside-width) var(--gap));
Copy after login

Now we can make sure that the sticky element does not overlap anything in the full screen element.

Here is a solution that contains horizontal bugs:

Here is a solution that includes horizontal bug fixes:

The fix is ​​to hide the body's x-axis overflow, which is usually a good idea:

 body {
  max-width: 100%;
  overflow-x: hidden;
}
Copy after login

This is a completely feasible solution and we can end there. But what's the fun of this? There is usually more than one way to accomplish something, so let's look at another.

Solution 2: Fill calculation

Instead of using centered mesh containers and pseudo-elements, we can achieve the same effect by configuring the mesh. Let's start by defining the grid, like we did last time:

 .grid {
  display: grid;
  grid-gap: var(--gap);
  grid-template-columns: var(--cols);
}
Copy after login

Similarly, we use custom properties to define gaps and template columns:

 :root {
  --gap: 20px;
  --gutter: 1px;
  --cols: var(--gutter) 1fr var(--gutter);
}
Copy after login

We display three columns on windows smaller than 768px. The middle column takes up as much space as possible, while the other two columns are only used for forced horizontal gaps.

 @media screen and (max-width: 767px) {
  .box {
    grid-column: 2 / -2;
  }
}
Copy after login

Note that all grid elements are placed in the middle column.

On windows larger than 768px, we define a --max-width variable that limits the width of the inner column. We also define --aside-width , which is the width of the sticky element. Again, this ensures that the sticky element does not position over anything within the full screen element.

 :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;
  }
}
Copy after login

Next, we will calculate the margin width. The calculation formula is:

 --gutter: calc((100% - (var(--max-width))) / 2 - var(--gap));
Copy after login

100% of which is the window width. First, we subtract the maximum width of the inner column from the window width. We then divide the result by 2 to create the margin. Finally, we subtract the grid gap to get the correct width of the margin column.

Now let's push .box--hero element aside so that it starts with the first column of the grid:

 @media screen and (min-width: 768px) {
  .box--hero {
    grid-column-start: 2;
  }
}
Copy after login

This will automatically push the sticky box so it follows the hero element. We can also clearly define the position of the sticky box as follows:

 .box--sticky {
  grid-column: 3 / span 1;
}
Copy after login

Finally, let's create a full screen element by setting grid-column to 1 / -1 . This tells the element to start the content from the first grid item and spans to the last grid item.

 @media screen and (min-width: 768px) {  
  .box--bleed {
    grid-column: 1 / -1;
  }
}
Copy after login

To center content, we will calculate the left and right padding. The left side fill is equal to the size of the margin column plus the grid gap. The right fill is equal to the size of the left fill, plus another grid gap and the width of the sticky element.

 @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));
  }
}
Copy after login

Here is the final solution:

I prefer this solution because it does not use the window unit in question.

I like CSS calculations. Using math is not always straightforward, especially when combining different units, such as 100% . Finding out what 100% means is half the job.

I also like to use CSS to solve simple but complex layouts, like this one. Modern CSS has native solutions—such as mesh, sticky positioning and computing—eliminate complex and rather heavy JavaScript solutions. Let's leave the dirty work to the browser!

Do you have a better solution or a different approach to this? I'd love to hear what you think.

The above is the detailed content of How to Get Sticky and Full-Bleed Elements to Play Well Together. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1655
14
PHP Tutorial
1252
29
C# Tutorial
1226
24
Google Fonts   Variable Fonts Google Fonts Variable Fonts Apr 09, 2025 am 10:42 AM

I see Google Fonts rolled out a new design (Tweet). Compared to the last big redesign, this feels much more iterative. I can barely tell the difference

How to Create an Animated Countdown Timer With HTML, CSS and JavaScript How to Create an Animated Countdown Timer With HTML, CSS and JavaScript Apr 11, 2025 am 11:29 AM

Have you ever needed a countdown timer on a project? For something like that, it might be natural to reach for a plugin, but it’s actually a lot more

HTML Data Attributes Guide HTML Data Attributes Guide Apr 11, 2025 am 11:50 AM

Everything you ever wanted to know about data attributes in HTML, CSS, and JavaScript.

How to select a child element with the first class name item through CSS? How to select a child element with the first class name item through CSS? Apr 05, 2025 pm 11:24 PM

When the number of elements is not fixed, how to select the first child element of the specified class name through CSS. When processing HTML structure, you often encounter different elements...

Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Apr 05, 2025 pm 05:51 PM

Questions about purple slash areas in Flex layouts When using Flex layouts, you may encounter some confusing phenomena, such as in the developer tools (d...

How We Created a Static Site That Generates Tartan Patterns in SVG How We Created a Static Site That Generates Tartan Patterns in SVG Apr 09, 2025 am 11:29 AM

Tartan is a patterned cloth that’s typically associated with Scotland, particularly their fashionable kilts. On tartanify.com, we gathered over 5,000 tartan

A Proof of Concept for Making Sass Faster A Proof of Concept for Making Sass Faster Apr 16, 2025 am 10:38 AM

At the start of a new project, Sass compilation happens in the blink of an eye. This feels great, especially when it’s paired with Browsersync, which reloads

See all articles