惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News - Newest:
Hacker News - Newest: "LLM"
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
H
Heimdal Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
N
News and Events Feed by Topic
H
Hacker News: Front Page
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
SecWiki News
SecWiki News
N
News | PayPal Newsroom
T
Tor Project blog
W
WeLiveSecurity
A
Arctic Wolf
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
月光博客
月光博客
AWS News Blog
AWS News Blog
D
Docker
C
CERT Recently Published Vulnerability Notes
MyScale Blog
MyScale Blog
Google Online Security Blog
Google Online Security Blog
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
I
InfoQ
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
Hacker News: Ask HN
Hacker News: Ask HN
Blog — PlanetScale
Blog — PlanetScale
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
Recorded Future
Recorded Future
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
The Exploit Database - CXSecurity.com
D
DataBreaches.Net
S
Security Affairs
WordPress大学
WordPress大学
T
Threatpost
Microsoft Security Blog
Microsoft Security Blog
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
S
SegmentFault 最新的问题
B
Blog RSS Feed
Project Zero
Project Zero
P
Proofpoint News Feed

CSS Articles by Temani Afif

Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks Let’s Play With Gap Decorations! How to Control Infinite CSS Animations (Part 2 of 2) How to Control Infinite CSS Animations (Part 1 of 2) Two Circles, One Arrow, and Anchor Positioning Making a Responsive Pyramidal Grid With Modern CSS | CSS-Tricks How to Create a CSS-only Elastic Text Effect Making Complex CSS Shapes Using shape() | CSS-Tricks Responsive Hexagon Grid Using Modern CSS | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 2) | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 1) | CSS-Tricks Perfectly Pointed Tooltips: To The Corners Perfectly Pointed Tooltips: All Four Sides Perfectly Pointed Tooltips: A Foundation Sequential linear() Animation With N Elements | CSS-Tricks Infinite Marquee Animation using Modern CSS Better CSS Shapes Using shape() — Part 4: Close and Move | CSS-Tricks Drawing CSS Shapes using corner-shape Better CSS Shapes Using shape() — Part 3: Curves | CSS-Tricks Better CSS Shapes Using shape() — Part 2: More on Arcs | CSS-Tricks Better CSS Shapes Using shape() — Part 1: Lines and Arcs | CSS-Tricks Creating Blob Shapes using clip-path: shape() Creating Flower Shapes using clip-path: shape() Custom progress element using the attr() function A CSS-Only Star Rating Component and More! (Part 2) | CSS-Tricks A CSS-Only Star Rating Component and More! (Part 1) | CSS-Tricks How to Create Wavy Boxes Using CSS Full-Bleed Layout with Modern CSS Fancy Menu Navigation Using Anchor Positioning | CSS-Tricks How to Create a Zig-Zag Box Using CSS How to Create Zig-Zag CSS Loaders Using One Element Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations How to Create Filling CSS Loaders Using One Element How to Create Curved-Edge and Rounded-Edge Shapes Using CSS CSS Tricks That Use Only One Gradient | CSS-Tricks How to create Shapes with Inner Curves using CSS Mask Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations How Keyboard Navigation Works in a CSS Game How To Create Cut-Out Shapes using The clip-path property The Modern Guide For Making CSS Shapes — Smashing Magazine css-shape.com: The Ultimate Collection of CSS-only Shapes ⚡️ Sliding 3D Image Frames In CSS — Smashing Magazine CSS Tricks To Master The clip-path Property Creating Wavy Circles with Fancy Animations in CSS Modern CSS Tooltips And Speech Bubbles (Part 2) — Smashing Magazine Do you need a Tooltip or a Speech Bubble? I have created 100 using CSS 😲 Modern CSS Tooltips And Speech Bubbles (Part 1) — Smashing Magazine Creating Flower Shapes using CSS Mask & Trigonometric Functions CSS Shapes: The Triangle The Complex But Awesome CSS border-image Property — Smashing Magazine CSS Tricks to add 3D Effects to your Text CSS Responsive Multi-Line Ribbon Shapes (Part 2) — Smashing Magazine CSS Responsive Multi-Line Ribbon Shapes (Part 1) — Smashing Magazine I have made 100+ CSS-only Ribbon Shapes | The Perfect Collection 🎀 How to create a CSS-only infinite scroll animation Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2) — Smashing Magazine Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 1) — Smashing Magazine How to Create CSS Ribbon Shapes with a Single Element CSS Shapes: The Ribbon Revealing Images With CSS Mask Animations — Smashing Magazine css-loaders.com: The Biggest Collection of Loading Animations (more than 500 🤯) How To Define An Array Of Colors With CSS — Smashing Magazine CSS effects on images II Shines, Perspective, And Rotations: Fancy CSS 3D Effects For Images — Smashing Magazine What's your Lucky CSS Pattern? Check It Now! How to Add a CSS Reveal Animation to Your Images Modern Layouts using CSS Grid I created 100+ unique CSS patterns | The best collection 🤩 How to Create a Custom Range Slider Using CSS CSS Shapes: The Heart CSS Shapes: Polygon & Starburst A Text Reveal Animation using CSS CSS Tip: learn CSS the easy way! How to build a CSS-only accordion How to create Breadcrumb Navigation with CSS Different Ways to Get CSS Gradient Shadows | CSS-Tricks A CSS-only responsive Stepper component A Fancy Hover Effect For Your Avatar | CSS-Tricks How to make a zoom effect using CSS Creating a Custom Cursor using CSS CSS Infinite 3D Sliders | CSS-Tricks CSS Infinite Slider Flipping Through Polaroid Images | CSS-Tricks How to create a responsive sidebar menu using CSS CSS Infinite and Circular Rotating Image Slider | CSS-Tricks Making Static Noise From a Weird CSS Gradient Bug | CSS-Tricks CSS Grid and Custom Shapes, Part 3 | CSS-Tricks Fancy Image Decorations: Outlines and Complex Animations | CSS-Tricks Fancy Image Decorations: Masks and Advanced Hover Effects | CSS-Tricks Fancy Image Decorations: Single Element Magic | CSS-Tricks How to create an infinite image slider using CSS How to Create Wavy Shapes & Patterns in CSS | CSS-Tricks How I Made a Pure CSS Puzzle Game | CSS-Tricks How to create a Tooltip/Speech Bubble using CSS CSS Grid and Custom Shapes, Part 2 | CSS-Tricks CSS Grid and Custom Shapes, Part 1 | CSS-Tricks Zooming Images in a Grid Layout | CSS-Tricks How to create a CSS-only loader with one element Exploring CSS Grid’s Implicit Grid and Auto-Placement Powers | CSS-Tricks How to create background pattern using CSS & conic-gradient Single Element Loaders: The Bars | CSS-Tricks
How to Get the Width/Height of Any Element in Only CSS
Temani Afif on July 25, 2024 · 2024-07-25 · via CSS Articles by Temani Afif

Getting the dimension of an element using JavaScript is a trivial task. You barely even need to do anything. If you have a reference to an element, you’ve got the dimensions (i.e. el.offsetWidth / el.offsetHeight). But we aren’t so lucky in CSS. While we’re able to react to elements being particular sizes with @container queries, we don’t have access to a straight up number we could use to, for example, display on the screen.

It may sound impossible but it’s doable! There are no simple built-in functions for this, so get ready for some slightly hacky experimentation.

Note: At time of writing, only Chrome (and Edge) have the full support of the features we will be using so consider those browsers to read the article.

Let’s start with a demo:

This demo has a simple layout with elements that will all have different sizes. Each rectangular element displays it’s own width/height. You can resize the browser or adjust the content; the values will update automatically.

Don’t try to find the hidden JavaScript, it’s 100% CSS magic, powered mostly by scroll-driven animations.

Scroll-Driven animations is one of the most popular new CSS features in 2024. It unlocked a lot of possibilities and solved some common problems.

How are these features relevant to this situation of figuring out an element’s dimensions, though?

The terms “scroll” and “animation” tend to bring to mind, uhh, animating stuff on scroll. To be fair, that is the main purpose:

It allows you to animate property values based on a progression along a scroll-based timeline instead of the default time-based document timeline. This means that you can animate an element by scrolling a scrollable element, rather than just by the passing of time.

MDN

But we can think about it differently and achieve more than a simple animation on scroll. If you keep reading the MDN page, it explains there are two types of “scroll-based timelines”. In our case, we will consider the “view progress timeline”.

You progress this timeline based on the change in visibility of an element (known as the subject) inside a scroller. The visibility of the subject inside the scroller is tracked as a percentage of progress.

MDN

With this type of scroll timeline, there are three relevant elements: the scroller which is the container having the scroll, the subject which is an element moving inside the container and the animation that will progress based on the position of the “subject” inside the “scroller”.

The three elements are linked with each other. To identify the progress of the animation we need to know the position of the subject inside the scroller and for this, we need to know the dimension of the scroller, the dimension of the subject, and the offset of the subject (the distance between the subject and the edges of the scroller).

So our equation contains four variables:

  1. Dimension of the scroller
  2. Dimension of the subject
  3. Progress of the animation
  4. Offset of the subject

If three variables are known, we can automatically find the missing one. In our case, the missing variable will be the “dimension of scroller” and that’s how we are going to find the width/height of any element (an element that will a be scroller).

How Does it Work?

Let’s dive into the theory and get to how scroll-driven animations are actually used to do this. It won’t be long and boring, I promise! I’ll be using width as the dimension being measured, but height would use the same logic just on the other axis.

Consider the following figure:

We have a container (the scroller) and an element inside it (the subject) placed on the left. There are two special positions within the container. The 0% position is when the element is at the right (inside the container) and the 100% position is when the element has exited the container from the left (outside the container).

The movement of the subject between 0% and 100% will define the percentage of the progression but our element will not move so the percentage will be fixed. Let’s call it P. We also know the width of the subject and we need to find the width of the scroller.

Remember the variables we talked about. Considering this configuration, we already know three of them: “the width of the subject”, “the offset of the subject” (fixed to the left edge), and the “progress of the animation” (since the subject is fixed). To make things easier, let’s consider that the width of the scroller is a multiplier of the width of the subject:

W = N * S.

The goal is to find the N or more precisely, we need to find the relation between the P and N. I said the P is fixed, but in reality it’s only fixed when the scroller width is fixed which is logical. But if the width of the scroller changes, the progress will also change, that’s why we need to find the formula between the progress and the width.

Let’s start with the case where the width of the scroller is equal to twice the width of the subject, we get the following:

The subject is in the middle between 0% and 100% so the progress in this case is 50%. For N = 2 we get P = 50%.

Let’s try for N = 3:

Now we have two extra slots in addition to the 0% and 100%. If we suppose that the subject can only be placed inside one of the 4 slots, we can have the following progress: 0%33.33%66.67%100%. But the subject is always placed at the before-the-last slot so the progress in this case is equal to 66.67% or, seen differently, it’s equal to 100% - 100%/3 (100%/3 is the progression step).

Are you seeing the pattern? If the width of the scroller is equal to N times the width of the subject we will have N+1 slots (including 0% and 100%) so the step between each slot is equal to 100%/N and the subject is located at the before-the-last slot so the progress is equal to 100% - 100%/N.

We have our equation: P = 100% - 100%/N so N = 100%/(100% - P).

If we convert the percentage to values between 0 and 1 we get N = 1/(1 - P) and the width we are looking for is equal to W = N * S = S/(1 - P).

Now If we consider a width for the subject equal to 1px, we get W = 1px/(1 - P) and without the unit, we have W = 1/(1 - P).

Let’s Write Some Code

Enough theory! Let’s transform all this into code. We start with this structure:

<div class="container"></div>Code language: HTML, XML (xml)
.container {
  overflow: auto;
  position: relative;
}
.container:before {
  content: "";
  position: absolute;
  left: 0;
  width: 1px;
}Code language: CSS (css)

The scroller element is the container and the subject element is a pseudo-element. I am using position: absolute so the subject doesn’t affect the width of the container (the value we need to calculate). Like described in the previous section, it’s placed at the left of the container with 1px of width.

Next, we define a named timeline linked to the pseudo-element (the subject)

.container {
  timeline-scope: --cx;
}
.container:before {
  view-timeline: --cx inline
}Code language: CSS (css)

The MDN description of the property:

The view-timeline CSS shorthand property is used to define a named view progress timeline, which is progressed through based on the change in visibility of an element (known as the subject) inside a scrollable element (scroller). view-timeline is set on the subject.

We consider the inline (horizontal) axis. We need to also use timeline-scope to give the container access to the view progress. By default, a named timeline is scoped to the element where it’s defined (and its descendants) but we can change this to make it available at any level.

Why not define the scope at the html level, then?

Enlarging the scope to all the elements may sound like a good idea, but it’s not. We may need to use the same code for different elements so limiting the scope allows us to reuse the same code and keep the same naming.

I won’t spend too much time detailing the scope feature but don’t forget about it. If the code doesn’t work as intended, it’s probably a scoping issue.

Now let’s define the animation:

@property --x {
  syntax: "<number>";
  inherits: true;
  initial-value: 0; 
}
.container {
  animation: x linear;
  animation-timeline: --cx;
  animation-range: entry 100% exit 100%; 
}
@keyframes x {
  0%   { --x: 0; }
  100% { --x: 1; }
}Code language: CSS (css)

We define a keyframes that animates a variable from 0 to 1. We have to register that variable with a number type to be able to animate it. We run the animation on the container with a linear easing and define the timeline using animation-timeline.

At this step, we told the browser to consider the named timeline defined on the pseudo-element (the subject) as the reference for the animation progress. And that progress will be stored in the --x variable. At 50%, we have --x: 0.5, at 70%, we have --x: 0.7, and so on.

The last step is to add the formula we identified earlier:

@property --w {
  syntax: "<integer>";
  inherits: true;
  initial-value: 0; 
}
.container {
  --w: calc(1/(1 - var(--x)));
}Code language: CSS (css)

The --w variable will contain the width in pixel of the container as a unitless value. It’s important to notice the “unitless” part. It gives us a lot of flexibility as we can integrate it within any formula. If you are a CSS hacker like me, you know what I mean!

What about that animation-range: entry 100% exit 100%;?

In addition to using a named timeline to define which element control the progress, we can also control the range of the animation. In other words, we can explicitly define where the 0% and 100% progress are located within the timeline.

Let’s get back to the first figure where I am showing the 0% and 100% progress.

The 0% is when the subject has completely entered the scroller from the right. We can express this using animation-range-start: entry 100%.

The 100% is when the subject has completely exited the scroller from the left. We can express this using animation-range-end: exit 100%.

Or using the shorthand:

animation-range: entry 100% exit 100%;Code language: CSS (css)

If you are new to scroll-driven animations, this part is not easy to grasp, so don’t worry if you don’t fully understand it. It requires some practice to build a mental model for it. Here is a good online tool that can help you visualize the different values.

Now, we do the same for the height and we are done. Here is the first demo again so you can inspect the full code.

Notice that I am using another pseudo-element to show the values. Let’s consider this as our first use case. Being able to get the width/height of any element and show them using only CSS is super cool!

.size::after {
  content: counter(w) "x" counter(h);
  counter-reset: w var(--w) h var(--h);
}Code language: CSS (css)

Are There Any Drawbacks?

Even if it seems to work fine, I still consider this as a “hack” to be used with caution. I am pretty sure it will fail in many situations so don’t consider this as a robust solution.

I also said “any element” in the title but in reality not all of them. It’s mandatory to be able to have a child element (the subject) so we cannot apply this trick to elements like <img> for example.

You also need to add overflow: auto (or hidden) to the container to make it the scroller for the subject. If you plan to have overflowing content then this solution will give you some trouble.

The value you will get using this method will include the padding but not the border! Pay attention to this part and compare the values you get with the ones of the Dev tools. You may need to perform another calculation to get the real dimension of the element by adding or subtracting specific amounts.

Another drawback is related to the use of 1px as our unit. We assumed that the size is a multiplier of 1px (which is true in most cases) but if your element is having a size like 185.15px, this trick won’t work. We can overcome this by using a smaller width for the subject (something like 0.01px) but I don’t think it is worth making this hack more complex.

A Few Use Cases

The first use case we saw is to show the dimension of the element which is a cool feature and can be a good one for debugging purposes. Let’s dig into more use cases.

Getting the Screen Dimension

We already have the viewport units vh and vw that works fine but this method can give us the unitless pixel values. You may ask how to do this since the viewport is not a real element. The solution is to rely on position: fixed applied to any element on the page. A fixed element is positioned relative to the viewport so its scroller will the viewport.

If you check the code, you will see that I am relying on the HTML pseudo-element for the subject and I don’t need to define any overflow or position on the HTML element. Plus the values are available globally since they are defined inside the HTML element!

For this particular case, I also have another CSS trick to get the screen dimension with an easier method:

Calculating the Scrollbar Width

There is a slight difference between the two screen width calculating methods above. The first demo will not include the scrollbar width if the page has a lot of content but the second one will. This means that If we combine both methods we can get the width of scrollbar!

Cool right? In addition to the screen dimension, you can also have the width of the scrollbar. Both values are available at root level so you can use them anywhere on the page.

If you want, you can also get the scrollbar width using a different method like I am detailing here: Get the scrollbar width using only CSS

Counting Stuff

All the calculations we did were based on the 1px size of the subject. If we change this to something else we can do some interesting counting. For example, if we consider 1lh (the height of the line box) we can count the number of lines inside a text.

Here is the version where you can edit the content. The number of lines will adjust based on the content you will enter.

Note how I am playing with the scope in this example. I am making the variable available at a higher level to be able to show the count inside a different element. Not only we can count the numbers of lines but we can also show the result anywhere on the page.

Can you think about something else to count? Share your example in the comment section.

Transferring Sizes

Being able to control the scope means that we can transfer the size of an element to another one on the page.

Here is an example where resizing the left element will also resize the right one!

Another important part of this trick is being able to get the width/height values as integer. This allows us to use them within any formula and append any unit to them.

Here is an example, where resizing the left element will rotate/scale the right one.

I have mapped the width with the rotation and the height with the scaling. Cool right? We can get the width/height of an element, have them as an integer, and transfer them to another element to do whatever we want. CSS is magic!

Conclusion

I hope you enjoyed this funny experiment. I still insist on the fact that it’s a hacky workaround to do something that was not possible using CSS. Use it for fun, use it to experiment with more CSS-only ideas but think twice before including this into a real project. Using one line of JavaScript code to get the dimension of an element is safer. Not all CSS-only tricks are a good replacement for JavaScript.

This said, if you find an interesting use case or you have another CSS-only experimentation where this trick can be useful, share it in the comment section.

If you’re interested in more experimentation with scroll-eriven animations check the following articles:

Article Series