{"id":3119,"date":"2024-07-25T09:14:28","date_gmt":"2024-07-25T14:14:28","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=3119"},"modified":"2025-01-05T16:22:43","modified_gmt":"2025-01-05T21:22:43","slug":"how-to-get-the-width-height-of-any-element-in-only-css","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/how-to-get-the-width-height-of-any-element-in-only-css\/","title":{"rendered":"How to Get the Width\/Height of Any Element in Only CSS"},"content":{"rendered":"\n<p>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\u2019ve got the dimensions (i.e.&nbsp;<code>el.offsetWidth<\/code>&nbsp;\/&nbsp;<code>el.offsetHeight<\/code>). But we aren\u2019t so lucky in CSS. While we\u2019re able to&nbsp;<em>react<\/em>&nbsp;to elements being particular sizes with&nbsp;<code>@container<\/code>&nbsp;queries, we don\u2019t have access to a straight up number we could use to, for example, display on the screen.<\/p>\n\n\n\n<p>It may sound impossible but it\u2019s doable! There are no simple built-in functions for this, so get ready for some slightly hacky experimentation.<\/p>\n\n\n\n<p class=\"learn-more\">Note: At time of writing, <em>only<\/em> Chrome (and Edge) have the full support of the features we will be using so consider those browsers to read the article.<\/p>\n\n\n\n<p>Let\u2019s start with a demo:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" src=\"\/\/codepen.io\/anon\/embed\/MWMyYeP\/5174eddd2477e3dd0308063abd43c46a?height=450&amp;theme-id=47434&amp;slug-hash=MWMyYeP\/5174eddd2477e3dd0308063abd43c46a&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" title=\"CodePen Embed MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>This demo has a simple layout with elements that will all have different sizes. Each rectangular element displays it\u2019s own width\/height. You can resize the browser or adjust the content; the values will update automatically.<\/p>\n\n\n\n<p>Don\u2019t try to find the hidden JavaScript, it\u2019s 100% CSS magic, powered mostly by scroll-driven animations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"why-scroll-driven-animations\">Why Scroll-Driven Animations?<\/h2>\n\n\n\n<p><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_scroll-driven_animations\">Scroll-Driven animations<\/a>&nbsp;is one of the most popular new CSS features in 2024. It unlocked a lot of possibilities and solved some common problems.<\/p>\n\n\n\n<p>How are these features relevant to this situation of figuring out an element\u2019s dimensions, though?<\/p>\n\n\n\n<p>The terms \u201cscroll\u201d and &#8220;animation\u201d tend to bring to mind,&nbsp;<em>uhh<\/em>, animating stuff on scroll. To be fair, that is the main purpose:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>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.<\/p>\n<cite><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_scroll-driven_animations\">MDN<\/a><\/cite><\/blockquote>\n\n\n\n<p>But we can think about it differently and achieve more than a simple animation on scroll. If you keep reading the&nbsp;MDN page, it explains there are two types of \u201cscroll-based timelines\u201d. In our case, we will consider the \u201c<em>view progress timeline<\/em>\u201d.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>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.<\/p>\n<cite><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_scroll-driven_animations\">MDN<\/a><\/cite><\/blockquote>\n\n\n\n<p>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 \u201csubject\u201d inside the \u201cscroller\u201d.<\/p>\n\n\n\n<p>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).<\/p>\n\n\n\n<p>So our equation contains four variables:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Dimension of the scroller<\/li>\n\n\n\n<li>Dimension of the subject<\/li>\n\n\n\n<li>Progress of the animation<\/li>\n\n\n\n<li>Offset of the subject<\/li>\n<\/ol>\n\n\n\n<p>If&nbsp;<em>three<\/em>&nbsp;variables are known, we can automatically find the missing one. In our case, the missing variable will be the \u201cdimension of scroller\u201d and that\u2019s how we are going to find the width\/height of any element (an element that will a be scroller).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-does-it-work\">How Does it Work?<\/h2>\n\n\n\n<p>Let\u2019s dive into the theory and get to how scroll-driven animations are actually used to do this. It won\u2019t be long and boring, I promise! I\u2019ll be using&nbsp;<code>width<\/code>&nbsp;as the dimension being measured, but&nbsp;<code>height<\/code>&nbsp;would use the same logic just on the other axis.<\/p>\n\n\n\n<p>Consider the following figure:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"342\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_0.png?resize=1024%2C342&#038;ssl=1\" alt=\"\" class=\"wp-image-3123\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_0.png?resize=1024%2C342&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_0.png?resize=300%2C100&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_0.png?resize=768%2C257&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_0.png?w=1071&amp;ssl=1 1071w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>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&nbsp;<code>0%<\/code>&nbsp;position is when the element is at the right (inside the container) and the&nbsp;<code>100%<\/code>&nbsp;position is when the element has exited the container from the left (outside the container).<\/p>\n\n\n\n<p>The movement of the subject between&nbsp;<code>0%<\/code>&nbsp;and&nbsp;<code>100%<\/code>&nbsp;will define the percentage of the progression but our element will not move so the percentage will be fixed. Let\u2019s call it&nbsp;<code>P<\/code>. We also know the width of the subject and we need to find the width of the scroller.<\/p>\n\n\n\n<p>Remember the variables we talked about. Considering this configuration, we already know three of them: \u201cthe width of the subject\u201d, \u201cthe offset of the subject&#8221; (fixed to the left edge), and the \u201cprogress of the animation\u201d (since the subject is fixed). To make things easier, let\u2019s consider that the width of the scroller is a multiplier of the width of the subject:<\/p>\n\n\n\n<p><code>W = N * S<\/code>.<\/p>\n\n\n\n<p>The goal is to find the&nbsp;<code>N<\/code>&nbsp;or more precisely, we need to find the relation between the <strong>P<\/strong> and&nbsp;<code>N<\/code>. I said the <strong>P<\/strong> is fixed, but in reality it\u2019s 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\u2019s why we need to find the formula between the progress and the width.<\/p>\n\n\n\n<p>Let\u2019s start with the case where the width of the scroller is equal to twice the width of the subject, we get the following:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"482\" height=\"313\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_2.png?resize=482%2C313&#038;ssl=1\" alt=\"\" class=\"wp-image-3124\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_2.png?w=482&amp;ssl=1 482w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_2.png?resize=300%2C195&amp;ssl=1 300w\" sizes=\"auto, (max-width: 482px) 100vw, 482px\" \/><\/figure>\n<\/div>\n\n\n<p>The subject is in the middle between&nbsp;<code>0%<\/code>&nbsp;and&nbsp;<code>100%<\/code>&nbsp;so the progress in this case is&nbsp;<code>50%<\/code>. For&nbsp;<code>N = 2<\/code>&nbsp;we get&nbsp;<code>P = 50%<\/code>.<\/p>\n\n\n\n<p>Let\u2019s try for&nbsp;<code>N = 3<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"482\" height=\"313\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_3.png?resize=482%2C313&#038;ssl=1\" alt=\"\" class=\"wp-image-3125\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_3.png?w=482&amp;ssl=1 482w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_3.png?resize=300%2C195&amp;ssl=1 300w\" sizes=\"auto, (max-width: 482px) 100vw, 482px\" \/><\/figure>\n<\/div>\n\n\n<p>Now we have two extra slots in addition to the&nbsp;<code>0%<\/code>&nbsp;and&nbsp;<code>100%<\/code>. If we suppose that the subject can only be placed inside one of the 4 slots, we can have the following progress:&nbsp;<code>0%<\/code>,&nbsp;<code>33.33%<\/code>,&nbsp;<code>66.67%<\/code>,&nbsp;<code>100%<\/code>. But the subject is always placed at the before-the-last slot so the progress in this case is equal to&nbsp;<code>66.67%<\/code>&nbsp;or, seen differently, it\u2019s equal to&nbsp;<code>100% - 100%\/3<\/code>&nbsp;(<code>100%\/3<\/code>&nbsp;is the progression step).<\/p>\n\n\n\n<p>Are you seeing the pattern? If the width of the scroller is equal to&nbsp;<code>N<\/code>&nbsp;times the width of the subject we will have&nbsp;<code>N+1<\/code>&nbsp;slots (including&nbsp;<code>0%<\/code>&nbsp;and&nbsp;<code>100%<\/code>) so the step between each slot is equal to&nbsp;<code>100%\/N<\/code>&nbsp;and the subject is located at the before-the-last slot so the progress is equal to&nbsp;<code>100% - 100%\/N<\/code>.<\/p>\n\n\n\n<p>We have our equation:&nbsp;<code>P = 100% - 100%\/N<\/code>&nbsp;so&nbsp;<code>N = 100%\/(100% - P)<\/code>.<\/p>\n\n\n\n<p>If we convert the percentage to values between&nbsp;<code>0<\/code>&nbsp;and&nbsp;<code>1<\/code>&nbsp;we get&nbsp;<code>N = 1\/(1 - P)<\/code>&nbsp;and the width we are looking for is equal to&nbsp;<code>W = N * S = S\/(1 - P)<\/code>.<\/p>\n\n\n\n<p>Now If we consider a width for the subject equal to&nbsp;<code>1px<\/code>, we get&nbsp;<code>W = 1px\/(1 - P)<\/code>&nbsp;and without the unit, we have&nbsp;<code>W = 1\/(1 - P)<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"lets-write-some-code\">Let\u2019s Write Some Code<\/h2>\n\n\n\n<p>Enough theory! Let\u2019s transform all this into code. We start with this structure:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">overflow<\/span>: auto;\n  <span class=\"hljs-attribute\">position<\/span>: relative;\n}\n<span class=\"hljs-selector-class\">.container<\/span><span class=\"hljs-selector-pseudo\">:before<\/span> {\n  <span class=\"hljs-attribute\">content<\/span>: <span class=\"hljs-string\">\"\"<\/span>;\n  <span class=\"hljs-attribute\">position<\/span>: absolute;\n  <span class=\"hljs-attribute\">left<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">1px<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The scroller element is the container and the subject element is a pseudo-element. I am using&nbsp;<code>position: absolute<\/code>&nbsp;so the subject doesn\u2019t affect the width of the container (the value we need to calculate). Like described in the previous section, it\u2019s placed at the left of the container with&nbsp;<code>1px<\/code>&nbsp;of width.<\/p>\n\n\n\n<p>Next, we define a named timeline linked to the pseudo-element (the subject)<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">timeline-scope<\/span>: --cx;\n}\n<span class=\"hljs-selector-class\">.container<\/span><span class=\"hljs-selector-pseudo\">:before<\/span> {\n  <span class=\"hljs-attribute\">view-timeline<\/span>: --cx inline\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The&nbsp;<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/view-timeline\">MDN<\/a>&nbsp;description of the property:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The&nbsp;<code>view-timeline<\/code>&nbsp;CSS&nbsp;shorthand property&nbsp;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).&nbsp;<code>view-timeline<\/code>&nbsp;is set on the subject.<\/p>\n<\/blockquote>\n\n\n\n<p>We consider the inline (horizontal) axis. We need to also use&nbsp;<code>timeline-scope<\/code>&nbsp;to give the container access to the view progress. By default, a named timeline is scoped to the element where it\u2019s defined (and its descendants) but we can change this to make it available at any level.<\/p>\n\n\n\n<p>Why not define the scope at the&nbsp;<code>html<\/code>&nbsp;level, then?<\/p>\n\n\n\n<p>Enlarging the scope to all the elements may sound like a good idea, but it\u2019s 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.<\/p>\n\n\n\n<p>I won\u2019t spend too much time detailing the scope feature but don\u2019t forget about it. If the code doesn\u2019t work as intended, it\u2019s probably a scoping issue.<\/p>\n\n\n\n<p>Now let\u2019s define the animation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@property<\/span> --x {\n  <span class=\"hljs-selector-tag\">syntax<\/span>: \"&lt;<span class=\"hljs-selector-tag\">number<\/span>&gt;\";\n  <span class=\"hljs-selector-tag\">inherits<\/span>: <span class=\"hljs-selector-tag\">true<\/span>;\n  <span class=\"hljs-selector-tag\">initial-value<\/span>: 0; \n}\n<span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">animation<\/span>: x linear;\n  <span class=\"hljs-attribute\">animation-timeline<\/span>: --cx;\n  <span class=\"hljs-attribute\">animation-range<\/span>: entry <span class=\"hljs-number\">100%<\/span> exit <span class=\"hljs-number\">100%<\/span>; \n}\n<span class=\"hljs-keyword\">@keyframes<\/span> x {\n  0%   { <span class=\"hljs-attribute\">--x<\/span>: <span class=\"hljs-number\">0<\/span>; }\n  100% { <span class=\"hljs-attribute\">--x<\/span>: <span class=\"hljs-number\">1<\/span>; }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We define a&nbsp;<code>keyframes<\/code>&nbsp;that animates a variable from&nbsp;<code>0<\/code>&nbsp;to&nbsp;<code>1<\/code>. We have&nbsp;<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/@property\">to register that variable<\/a>&nbsp;with a&nbsp;<code>number<\/code>&nbsp;type to be able to animate it. We run the animation on the container with a linear easing and define the timeline using&nbsp;<code>animation-timeline<\/code>.<\/p>\n\n\n\n<p>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&nbsp;<code>--x<\/code>&nbsp;variable. At&nbsp;<code>50%<\/code>, we have&nbsp;<code>--x: 0.5<\/code>, at&nbsp;<code>70%<\/code>, we have&nbsp;<code>--x: 0.7<\/code>, and so on.<\/p>\n\n\n\n<p>The last step is to add the formula we identified earlier:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@property<\/span> --w {\n  <span class=\"hljs-selector-tag\">syntax<\/span>: \"&lt;<span class=\"hljs-selector-tag\">integer<\/span>&gt;\";\n  <span class=\"hljs-selector-tag\">inherits<\/span>: <span class=\"hljs-selector-tag\">true<\/span>;\n  <span class=\"hljs-selector-tag\">initial-value<\/span>: 0; \n}\n<span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">--w<\/span>: <span class=\"hljs-built_in\">calc<\/span>(<span class=\"hljs-number\">1<\/span>\/(<span class=\"hljs-number\">1<\/span> - var(--x)));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The&nbsp;<code>--w<\/code>&nbsp;variable will contain the width in pixel of the container as a unitless value. It\u2019s important to notice the \u201cunitless\u201d 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!<\/p>\n\n\n\n<p>What about that&nbsp;<code>animation-range: entry 100% exit 100%;<\/code>?<\/p>\n\n\n\n<p>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&nbsp;<code>0%<\/code>&nbsp;and&nbsp;<code>100%<\/code>&nbsp;progress are located within the timeline.<\/p>\n\n\n\n<p>Let\u2019s get back to the first figure where I am showing the <code>0%<\/code> and <code>100%<\/code> progress.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"342\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_1.png?resize=1024%2C342&#038;ssl=1\" alt=\"\" class=\"wp-image-3122\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_1.png?resize=1024%2C342&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_1.png?resize=300%2C100&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_1.png?resize=768%2C257&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/diagram_1.png?w=1071&amp;ssl=1 1071w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>The&nbsp;<code>0%<\/code>&nbsp;is when the subject has&nbsp;<strong>completely<\/strong>&nbsp;entered the scroller from the right. We can express this using&nbsp;<code>animation-range-start: entry 100%<\/code>.<\/p>\n\n\n\n<p>The&nbsp;<code>100%<\/code>&nbsp;is when the subject has&nbsp;<strong>completely<\/strong>&nbsp;exited the scroller from the left. We can express this using&nbsp;<code>animation-range-end: exit 100%<\/code>.<\/p>\n\n\n\n<p>Or using the shorthand:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">animation-range<\/span>: <span class=\"hljs-selector-tag\">entry<\/span> 100% <span class=\"hljs-selector-tag\">exit<\/span> 100%;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you are new to scroll-driven animations, this part is not easy to grasp, so don\u2019t worry if you don\u2019t fully understand it. It requires some practice to build a mental model for it. Here is a&nbsp;<a href=\"https:\/\/scroll-driven-animations.style\/tools\/view-timeline\/ranges\/\">good online tool<\/a>&nbsp;that can help you visualize the different values.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" src=\"\/\/codepen.io\/anon\/embed\/MWMyYeP\/5174eddd2477e3dd0308063abd43c46a?height=450&amp;theme-id=47434&amp;slug-hash=MWMyYeP\/5174eddd2477e3dd0308063abd43c46a&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" title=\"CodePen Embed MWMyYeP\/5174eddd2477e3dd0308063abd43c46a\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Notice that I am using another pseudo-element to&nbsp;<em>show<\/em>&nbsp;the values. Let\u2019s 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!<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.size<\/span><span class=\"hljs-selector-pseudo\">::after<\/span> {\n  <span class=\"hljs-attribute\">content<\/span>: <span class=\"hljs-built_in\">counter<\/span>(w) <span class=\"hljs-string\">\"x\"<\/span> <span class=\"hljs-built_in\">counter<\/span>(h);\n  <span class=\"hljs-attribute\">counter-reset<\/span>: w <span class=\"hljs-built_in\">var<\/span>(--w) h <span class=\"hljs-built_in\">var<\/span>(--h);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"are-there-any-drawbacks\">Are There Any Drawbacks?<\/h2>\n\n\n\n<p>Even if it seems to work fine, I still consider this as a \u201chack\u201d to be used with caution. I am pretty sure it will fail in many situations so don\u2019t consider this as a robust solution.<\/p>\n\n\n\n<p>I also said \u201cany element\u201d in the title but in reality not all of them. It\u2019s mandatory to be able to have a child element (the subject) so we cannot apply this trick to elements like&nbsp;<code>&lt;img&gt;<\/code>&nbsp;for example.<\/p>\n\n\n\n<p>You also need to add&nbsp;<code>overflow: auto<\/code>&nbsp;(or&nbsp;<code>hidden<\/code>) 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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Another drawback is related to the use of&nbsp;<code>1px<\/code>&nbsp;as our unit. We assumed that the size is a multiplier of&nbsp;<code>1px<\/code>&nbsp;(which is true in most cases) but if your element is having a size like&nbsp;<code>185.15px<\/code>, this trick won\u2019t work. We can overcome this by using a smaller width for the subject (something like&nbsp;<code>0.01px<\/code>) but I don\u2019t think it is worth making this hack more complex.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"a-few-use-cases\">A Few Use Cases<\/h2>\n\n\n\n<p>The first use case we saw is to&nbsp;<em>show<\/em>&nbsp;the dimension of the element which is a cool feature and can be a good one for debugging purposes. Let\u2019s dig into more use cases.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"getting-the-screen-dimension\">Getting the Screen Dimension<\/h3>\n\n\n\n<p>We already have the viewport units&nbsp;<code>vh<\/code>&nbsp;and&nbsp;<code>vw<\/code>&nbsp;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&nbsp;<code>position: fixed<\/code>&nbsp;applied to any element on the page. A fixed element is positioned relative to the viewport so its scroller will the viewport.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_eYwZgqL\/a4b01cb145b565581e352c7ec25a64ec\" src=\"\/\/codepen.io\/anon\/embed\/eYwZgqL\/a4b01cb145b565581e352c7ec25a64ec?height=450&amp;theme-id=47434&amp;slug-hash=eYwZgqL\/a4b01cb145b565581e352c7ec25a64ec&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed eYwZgqL\/a4b01cb145b565581e352c7ec25a64ec\" title=\"CodePen Embed eYwZgqL\/a4b01cb145b565581e352c7ec25a64ec\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>If you check the code, you will see that I am relying on the HTML pseudo-element for the subject and I don\u2019t 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!<\/p>\n\n\n\n<p>For this particular case, I also have&nbsp;<a href=\"https:\/\/css-tip.com\/screen-dimension\/\">another CSS trick to get the screen dimension<\/a>&nbsp;with an easier method:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_ExBVLBW\" src=\"\/\/codepen.io\/anon\/embed\/ExBVLBW?height=450&amp;theme-id=47434&amp;slug-hash=ExBVLBW&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed ExBVLBW\" title=\"CodePen Embed ExBVLBW\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Calculating the Scrollbar Width<\/h3>\n\n\n\n<p>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!<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_rNEjyNj\" src=\"\/\/codepen.io\/anon\/embed\/rNEjyNj?height=450&amp;theme-id=47434&amp;slug-hash=rNEjyNj&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed rNEjyNj\" title=\"CodePen Embed rNEjyNj\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>If you want, you can also get the scrollbar width using a different method like I am detailing here:\u00a0<a href=\"https:\/\/css-tip.com\/width-scrollbar\/\">Get the scrollbar width using only CSS<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"counting-stuff\">Counting Stuff<\/h3>\n\n\n\n<p>All the calculations we did were based on the&nbsp;<code>1px<\/code>&nbsp;size of the subject. If we change this to something else we can do some interesting counting. For example, if we consider&nbsp;<code>1lh<\/code>&nbsp;(the height of the line box) we can count the number of lines inside a text.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_BagKWdm\/5805ffac8652437a6ede25a5af340a4b\" src=\"\/\/codepen.io\/anon\/embed\/BagKWdm\/5805ffac8652437a6ede25a5af340a4b?height=450&amp;theme-id=47434&amp;slug-hash=BagKWdm\/5805ffac8652437a6ede25a5af340a4b&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed BagKWdm\/5805ffac8652437a6ede25a5af340a4b\" title=\"CodePen Embed BagKWdm\/5805ffac8652437a6ede25a5af340a4b\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Here is the version where you can edit the content. The number of lines will adjust based on the content you will enter.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_RwzapLK\/08746cfe8d8e86eac463e70284a3ccd4\" src=\"\/\/codepen.io\/anon\/embed\/RwzapLK\/08746cfe8d8e86eac463e70284a3ccd4?height=450&amp;theme-id=47434&amp;slug-hash=RwzapLK\/08746cfe8d8e86eac463e70284a3ccd4&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed RwzapLK\/08746cfe8d8e86eac463e70284a3ccd4\" title=\"CodePen Embed RwzapLK\/08746cfe8d8e86eac463e70284a3ccd4\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Can you think about something else to count? Share your example in the comment section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"transferring-sizes\">Transferring Sizes<\/h3>\n\n\n\n<p>Being able to control the scope means that we can transfer the size of an element to another one on the page.<\/p>\n\n\n\n<p>Here is an example where resizing the left element will also resize the right one!<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_OJeNzoz\/ab8922c47f1f81858cbada8db185cc48\" src=\"\/\/codepen.io\/anon\/embed\/OJeNzoz\/ab8922c47f1f81858cbada8db185cc48?height=450&amp;theme-id=47434&amp;slug-hash=OJeNzoz\/ab8922c47f1f81858cbada8db185cc48&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed OJeNzoz\/ab8922c47f1f81858cbada8db185cc48\" title=\"CodePen Embed OJeNzoz\/ab8922c47f1f81858cbada8db185cc48\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Here is an example, where resizing the left element will rotate\/scale the right one.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_rNEeydE\/ca2f6f913f188febdfb9f23ff53190db\" src=\"\/\/codepen.io\/anon\/embed\/rNEeydE\/ca2f6f913f188febdfb9f23ff53190db?height=450&amp;theme-id=47434&amp;slug-hash=rNEeydE\/ca2f6f913f188febdfb9f23ff53190db&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed rNEeydE\/ca2f6f913f188febdfb9f23ff53190db\" title=\"CodePen Embed rNEeydE\/ca2f6f913f188febdfb9f23ff53190db\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>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!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>I hope you enjoyed this funny experiment. I still insist on the fact that it\u2019s 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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>If you&#8217;re interested in more experimentation&nbsp;with scroll-eriven animations check the following articles:<\/p>\n\n\n<div class=\"box article-series\">\n  <header>\n    <h3 class=\"article-series-header\">Article Series<\/h3>\n  <\/header>\n  <div class=\"box-content\">\n            <ol>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/custom-progress-element-using-anchor-positioning-scroll-driven-animations\/\">Custom Progress Element Using Anchor Positioning &amp; Scroll-Driven Animations<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/custom-range-slider-using-anchor-positioning-scroll-driven-animations\/\">Custom Range Slider Using Anchor Positioning &amp; Scroll-Driven Animations<\/a>\n            <\/li>\n                  <\/ol>\n        <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Unlike JavaScript, there is no simple built-in method in CSS to access an element&#8217;s width and height. But using some (call it hacky) modern CSS techniques, we can get our hands on the number and even use it.<\/p>\n","protected":false},"author":12,"featured_media":3127,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[7,57],"class_list":["post-3119","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css","tag-scroll-driven-animations"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-24-at-9.46.11%E2%80%AFAM.png?fit=1424%2C732&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=3119"}],"version-history":[{"count":11,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3119\/revisions"}],"predecessor-version":[{"id":4927,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3119\/revisions\/4927"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/3127"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=3119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=3119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=3119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}