search
HomeWeb Front-endCSS TutorialHow to Get Sticky and Full-Bleed Elements to Play Well Together

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>

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;
  }
}

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);
}

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;
}

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;
  }
}

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;
}

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);

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));

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;
}

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);
}

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

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

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;
  }
}

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;
  }
}

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

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

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;
  }
}

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;
}

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;
  }
}

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));
  }
}

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
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
What is CSS Grid?What is CSS Grid?Apr 30, 2025 pm 03:21 PM

CSS Grid is a powerful tool for creating complex, responsive web layouts. It simplifies design, improves accessibility, and offers more control than older methods.

What is CSS flexbox?What is CSS flexbox?Apr 30, 2025 pm 03:20 PM

Article discusses CSS Flexbox, a layout method for efficient alignment and distribution of space in responsive designs. It explains Flexbox usage, compares it with CSS Grid, and details browser support.

How can we make our website responsive using CSS?How can we make our website responsive using CSS?Apr 30, 2025 pm 03:19 PM

The article discusses techniques for creating responsive websites using CSS, including viewport meta tags, flexible grids, fluid media, media queries, and relative units. It also covers using CSS Grid and Flexbox together and recommends CSS framework

What does the CSS box-sizing property do?What does the CSS box-sizing property do?Apr 30, 2025 pm 03:18 PM

The article discusses the CSS box-sizing property, which controls how element dimensions are calculated. It explains values like content-box, border-box, and padding-box, and their impact on layout design and form alignment.

How can we animate using CSS?How can we animate using CSS?Apr 30, 2025 pm 03:17 PM

Article discusses creating animations using CSS, key properties, and combining with JavaScript. Main issue is browser compatibility.

Can we add 3D transformations to our project using CSS?Can we add 3D transformations to our project using CSS?Apr 30, 2025 pm 03:16 PM

Article discusses using CSS for 3D transformations, key properties, browser compatibility, and performance considerations for web projects.(Character count: 159)

How can we add gradients in CSS?How can we add gradients in CSS?Apr 30, 2025 pm 03:15 PM

The article discusses using CSS gradients (linear, radial, repeating) to enhance website visuals, adding depth, focus, and modern aesthetics.

What are pseudo-elements in CSS?What are pseudo-elements in CSS?Apr 30, 2025 pm 03:14 PM

Article discusses pseudo-elements in CSS, their use in enhancing HTML styling, and differences from pseudo-classes. Provides practical examples.

See all articles

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

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use