Tag: Height

Exploring the Complexities of Width and Height in CSS

The following article is co-authored by Uri Shaked and Michal Porag.

Let’s explore the complexities of how CSS computes the width and height dimensions of elements. This is based on countless late-night hours debugging and fiddling with lots of combinations of CSS properties, reading though the specs, and trying to figure out why some things seem to behave one way or another.

But before jumping in, let’s cover some basics so we’re all on the same page.

The basics

You have an element, and you want it to be 640px wide and 360px tall. These are just arbitrary numbers that conform to 16:9 pixel ratio. You can set them explicitly like this:

.element {   width: 640px;   height: 360px; }

Now, the design calls for some padding inside that element. So you modify the CSS:

.element {   width: 640px;   height: 360px;   padding: 10px; }

What is the rendered width and height of the element now? I bet you can guess… it’s not 640×360px anymore! It’s actually 660×380px, because the padding adds 10px to each side (i.e. top, right, bottom and left), for an additional 20px on both the height and width.

This has to do with the box-sizing property: if it’s set to content-box (the default value), the rendered size of the element is the width and height plus the padding and border. That might mean that the rendered size is bigger than we intend which is funny because it might wind up that an element’s declared width and height values are completely different than what’s rendered.

That’s the power of The CSS Box Model. It calculates width and height like so:

/* Width */ width + padding-left + padding-right + border-left + border-right  /* Height */ height + padding-top + padding-bottom + border-top + border-bottom

What we just saw is how the dimensions for a block element are computed. Block elements include any element that naturally takes up the full width that’s available. So, by nature, it doesn’t matter how much content the element contains because its width is always 100%, that is, until we alter it. Think of elements like <p>, <article>, <main>, <div>, and so many more.

But now we ought to look at inline elements because they behave differently when it comes to The Box Model and how their dimensions are computed. After that, we’ll look at the relationship between parent and child elements, and how they affect the width and height computations of each other.

The curious case of inline elements

As we just saw, the padding and border of any element are both included in the element’s computed width and height dimensions. Funny enough, there are cases where the width and height properties have no effect whatsoever. Such is the case when working with inline elements.

An inline element is an element that’s width and height are determined by the content it contains. Inline elements, such as a <span>, will completely ignore the width and height as well the the left and right margin properties because, well, the content is what determines the dimensions. Here, sometimes a visual can help.

Just look at how nesting a block element inside of an inline element breaks the inline element’s shape simply because the block element is not defined by the amount of content it contains, but rather the amount of available space. You can really see that in action when we add a border to the inline element. Look how the inline element abruptly stops where the paragraph comes in, then continues after the paragraph.

The span sees the paragraph, which interrupts the inline flow of the span and essentially breaks out of it. Fascinating stuff!

But there’s more! Look how the inline element completely overlooks width and margin, even when those are declared right on it.

Crazy!

Parent and child elements

The parent-child relationship is a common pattern. A parent element is one that contains other elements nested inside it. And those nested elements are the parent element’s children.

<!-- The parent element --> <div class="parent">   <!-- The children -->   <div class="child"></div>   <div class="another-child"></div>   <div class="twins">Whoa!</div> </div>

The width and height of an element gets super interesting with parent and child elements. Let’s look at all the interesting quirks we get with this.

Relative units

Let’s start with relative units. A relative unit is computed by its context, or relation to other elements. Yeah, that’s sort of a convoluted definition. There are several different types of relative units, but let’s take percentages as an example. We can say that an element is 100% wide.

<div class="child">   <!-- nothing yet --> </div>
.parent {   width: 100%; }

Cool. If we plop that element onto an empty page, it will take up 100% of the available horizontal space. And what that 100% computes to depends on the width of the browser, right? 100% of a browser that’s 1,500 pixels is 1,500 pixels wide. 100% of a browser that’s 500 pixels is 500 pixels wide. That’s what we mean by a relative unit. The actual computed value is determined by the context in which it’s used.

So, the astute reader may already be thinking: Hey, so that’s sort of like a child element that’s set to a parent element’s width. And that would be correct. The width of the child at 100% will compute based on the actual width of the parent element that contains it.

Height works much the same way: it’s relative to the parent’s height. For example, two parent elements with different height dimensions but identical children result in children with different heights.

Padding and margin

The width and height of parent-child combinations get even more interesting when we look at other properties, such as padding and margin. Apparently, when we specify a percentage value for padding or margin, it is always relative to the width of the parent, even when dealing with vertical edges.

Some clever designers have taken advantage of it to create boxes of equal width and height, or boxes that keep a certain aspect ratio when the page resizes. This is particularly useful for video or image content, but can also be (ab)used in creative ways. Go ahead, type whatever you want into the editable element in this demo. The box maintains a proportional height and width, no matter how much (or little) content is added.

This technique for creating aspect ratio boxes is lovingly referred to as the “padding hack.” Chris has covered it extensively. But now that we have the aspect-ratio property gaining wide browser support, there’s less reason to reach for it.

display: inline and inline-block

Now that we’ve taken looks at how parent and child element dimensions are computed, we should check out two other interesting property values that affect an element’s width: min-content and max-content.

These properties tell the browser to look at the content of the element in order to determine its width. For instance, if we have the text: “hello CSS encyclopedia, nice to meet you!”, the browser would calculate the space that text would take up on the screen, and use it as the width.

The difference between min-content and max-content lies in how the browser does this calculation. For max-content, the browser pretends it has infinite space, and lays all the text in a single line while measuring its width.

For min-content, the browser pretends it has zero space, so it puts every word / child inline element in a different line. Let’s see this in action:

We actually saw max-content in action when we looked at the difference between block and inline elements. Inline elements, remember, are only as wide and tall as the content they contain. We can make most elements inline elements just by declaring display: inline; on it.

Cool. Another weapon we have is display: inline-block;. That creates an inline element, but enhanced with block-level computations in The Box Model. In other words, it’s an inline element that respects margin, width and height. The best of both worlds!

Cyclic percentage size

Did that last point make sense? Well, hopefully I won’t confuse you with this:

The child element in this example has a relative width of 33%. The parent element does not have a width declared on it. How the heck is the child’s computed width get calculated when there’s nothing relative to it?

To answer that, we have to look at how the browser calculates the size of the elements in this example. We haven’t defined a specific width for the parent element, so the browser uses the initial value for width , which is auto. And since the parent element’s display is set to inline-block, auto behaves like max-content. And max-content, as we saw, should mean the parent element is as wide as the content in it, which is everything inside the child element.

So, the browser looks at the element’s content (children) to determine its width. However, the width of the child also depends on the parent’s width! Gah, this is weird!

The CSS Box Sizing Module specification calls this cyclic percentage sizing. I’m not sure why it’s called that exactly, but it details the complex math the browser has to do to (1) determine the parent element’s width, and (2) reconcile that width to the relative width of the child.

The process is actually pretty cool once you get over the math stuff. The browser starts by calculating a temporary width for the child before its declared value is applied. The temporary width the browser uses for the child is auto which we saw behaves like max-content which, in turn, tells the browser that the child needs to be as wide as the content it contains. And right now, that’s not the declared 33% value.

That max-content value is what the browser uses to calculate the parent’s width. The parent, you see, needs to be at least as wide as the content that it contains, which is everything in the child at max-content. Once that resolves, the browser goes back to the child element and applies the 33% value that’s declared in the CSS.

This is how it looks:

There! Now we know how a child element can contribute to the computed value of its parent.

M&Ms: the min- and max- properties

Hey, so you’re probably aware that the following properties exist:

  • min-width
  • min-height
  • max-width
  • max-height

Well, those have a lot to do with an element’s width and height as well. They specify the limits an element’s size. It’s like saying, Hey, browser, make sure this element is never under this width/height or above this width/height.

So, even if we have declared an explicit width on an element, say 100%, we can still cap that value by giving it a max-width:

element {   width: 100%;   max-width: 800px; }

This allows the browser to let the element take up as much space as it wants, up to 800 pixels. Let’s look what happens if we flip those values around and set the max-width to 100% and width to 800px:

element {   width: 800px;   max-width: 100%; }

Hey look, it seems to result in the exact same behavior! The element takes up all the space it needs until it gets to 800 pixels.

Apparently, things start to get more complex as soon as we add a parent element into the mix. This is the same example as above, with one notable change: now each element is a child of an inline-block element. Suddenly, we see a striking difference between the two examples:

Why the difference? To understand, let’s consider how the browser calculates the width of the elements in this example.

We start with the parent element (.parent). It has a display property set to inline-block, and we didn’t specify a width value for it. Just like before, the browser looks at the size of its children to determine its width. Each box in this example is wrapped in the .parent element.

The first box (#container1) has a percentage width value of 100%. The width of the parent resolves to the width of the text within (the child’s max-content), limited by the value we specified by max-width, and that is used to calculate the width of the child as well.

The second box (#container2) has a set width of 800px, so its parent width is also 800px — just wide enough to fit its child. Then, the child’s max-width is resolved relative to the parent’s final width, that is 800px. So both the parent and the child are 800px wide in this case.

So, even though we initially saw the two boxes behave the same when we swapped width and max-width values, we now know that isn’t always true. In this case, introducing a parent element set to display: inline-block; threw it all off!

Adding min(), max() and clamp() into the mix

The min(), max() and clamp() are three useful CSS functions that let us define the size of elements responsively… without media queries!

  • min(): Returns the minimum value of its arguments. The arguments can be given in different units, and we can even mix and match absolute and relative units, like min(800px, 100%).
  • max(): Returns the maximum value of its arguments. Just like min(), you can mix and match different units.
  • clamp(): A shorthand function for doing min and max at once: clamp(MIN, VAL, MAX) is resolved as max(MIN, min(VAL, MAX)). In other words, it will return VAL, unless it exceeds the boundaries defined by MIN and MAX, in which case it’ll return the corresponding boundary value.

Like this. Check out how we can effectively “re-write” the max-width example from above using a single CSS property:

.element {   width: min(800px, 100%); }  /* ...is equivalent to: */ .element {   width: 800px;   max-width: 100%; }

That would set the width of the element to 800px, but make sure we don’t exceed the width of the parent (100%). Just like before, if we wrap the element with an inline-block parent, we can observe it behaving differently than the max-width variation:

The width of the children (800px) is the same. However, if you enlarge the screen (or use CodePen’s 0.5x button to zoom out), you will notice that the second parent is actually larger.

It boils down to how the browser calculates the parent’s width: we didn’t specify a width for the parent, and as child’s width value is using relative units, the browser ignores it while calculating the parent’s width and uses the max-content child of the child, dictated by the “very long … long” text.

Wrapping up

Phew! It’s crazy that something as seemingly simple as width and height actually have a lot going on. Sure, we can set explicit width and height values on an element, but the actual values that render often end up being something completely different.

That’s the beauty (and, frankly, the frustration) with CSS. It’s so carefully considered and accounts for so many edge cases. I mean, the concept of The Box Model itself is wonderfully complex and elegant at the same time. Where else can we explicitly declare something in code and have it interpreted in different ways? The width isn’t always the width.

And we haven’t even touched on some other contributing factors to an element’s dimensions. Modern layout techniques, like CSS Flexbox and Grid introduce axes and track lines that also determine the rendered size of an element.


Authors: Uri Shaked and Michal Porag


The post Exploring the Complexities of Width and Height in CSS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,

How to Tame Line Height in CSS

In CSS, line-height is probably one of the most misunderstood, yet commonly-used attributes. As designers and developers, when we think about line-height, we might think about the concept of leading from print design — a term, interestingly enough, that comes from literally putting pieces of lead between lines of type. 

Leading and line-height, however similar, have some important differences. To understand those differences, we first have to understand a bit more about typography. 

An overview of typography terms

In traditional Western type design, a line of text is comprised of several parts: 

  • Baseline: This is the imaginary line on which the type sits. When you write in a ruled notebook, the baseline is the line on which you write.
  • Descender: This line sits just below the baseline. It is the line that some characters — like lowercase g, j, q, y and p  — touch below the baseline. 
  • X-height: This is (unsurprisingly) the height of a normal, lowercase x in a line of text. Generally, this is the height of other lowercase letters, although some may have parts of their characters that will exceed the x-height. For all intents and purposes, it servers as the perceived height of lowercase letters.
  • Cap-height: This is the height of most capital letters on a given line of text.
  • Ascender: A line that oftentimes appears just above the cap height where some characters like a lowercase h or b might exceed the normal cap height.
Illustrating the ascender, cap height, x-height, baseline and descender of the Lato font with The quick fox as sample text.

Each of the parts of text described above are intrinsic to the font itself. A font is designed with each of these parts in mind; however, there are some parts of typography that are left up to the type setter (like you and me!) rather than the designer. One of these is leading.

Leading is defined as the distance between two baselines in a set of type.

Two lines of text with an order box around the second line ofd text indicating the leading.

A CSS developer might think, “OK, leading is the line-height, let’s move on.” While the two are related, they are also different in some very important ways.

Let’s take a blank document and add a classic “CSS reset” to it:

* {   margin: 0;   padding: 0; }

This removes the margin and padding from every single element.

We’ll also use Lato from Google Fonts as our font-family.

We will need some content, so let’s an create an <h1> tag with some text and set the line-height to something obnoxiously huge, like 300px. The result is a single line of text with a surprising amount of space both above and below the single line of text.

When a browser encounters the line-height property, what it actually does is take the line of text and place it in the middle of a “line box” which has a height matching the element’s line-height. Instead of setting the leading on a font, we get something akin to padding one either side of the line box.

Two lines of text with orange borders around each line of text, indicating the line box for each line. The bottom border of the first line and the top border of the second line are touching.

As illustrated above, the line box wraps around a line of text where leading is created by using space below one line of text and above the next. This means that for every text element on a page there will be half of the leading above the first line of text and after the last line of text in a particular text block.

What might be more surprising is that explicitly setting the line-height and font-size on an element with the same value will leave extra room above and below the text. We can see this by adding a background color to our elements.

This is because even though the font-size is set to 32px, the actual text size is something less than that value because of the generated spacing.

Getting CSS to treat line-height like leading

If we want CSS to use a more traditional type setting style instead of the line box, we’ll want a single line of text to have no space either above or below it — but allow for multi-line elements to maintain their entire line-height value. 

It is possible to teach CSS about leading with a little bit of effort. Michael Taranto released a tool called Basekick that solves this very issue. It does so by applying a negative top margin to the ::before pseudo-elementand a translateY to the element itself. The end result is a line of text without any extra space around it.

The most up-to-date version of Basekick’s formula can be found in the source code for the Braid Design System from SEEK. In the example below, we are writing a Sass mixin to do the heavy lifting for us, but the same formula can be used with JavaScript, Less, PostCSS mixins, or anything else that provides these kinds of math features.

@function calculateTypeOffset($ lh, $ fontSize, $ descenderHeightScale) {   $ lineHeightScale: $ lh / $ fontSize;   @return ($ lineHeightScale - 1) / 2 + $ descenderHeightScale; } 
 @mixin basekick($ typeSizeModifier, $ baseFontSize, $ descenderHeightScale, $ typeRowSpan, $ gridRowHeight, $ capHeight) {   $ fontSize: $ typeSizeModifier * $ baseFontSize;   $ lineHeight: $ typeRowSpan * $ gridRowHeight;   $ typeOffset: calculateTypeOffset($ lineHeight, $ fontSize, $ descenderHeightScale);   $ topSpace: $ lineHeight - $ capHeight * $ fontSize;   $ heightCorrection: 0;      @if $ topSpace > $ gridRowHeight {     $ heightCorrection: $ topSpace - ($ topSpace % $ gridRowHeight);   }      $ preventCollapse: 1;      font-size: #{$ fontSize}px;   line-height: #{$ lineHeight}px;   transform: translateY(#{$ typeOffset}em);   padding-top: $ preventCollapse; 
   &::before {     content: "";     margin-top: #{-($ heightCorrection + $ preventCollapse)}px;     display: block;     height: 0;   } }

At first glance, this code definitely looks like a lot of magic numbers cobbled together. But it can be broken down considerably by thinking of it in the context of a particular system. Let’s take a look at what we need to know:

  • $ baseFontSize:This is the normal font-size for our system around which everything else will be managed. We’ll use 16px as the default value.
  • $ typeSizeModifier: This is a multiplier that is used in conjunction with the base font size to determine the font-size rule. For example, a value of 2 coupled with our base font size of 16px will give us font-size: 32px.
  • $ descenderHeightScale: This is the height of the font’s descender expressed as a ratio. For Lato, this seems to be around 0.11.
  • $ capHeight: This is the font’s specific cap height expressed as a ratio. For Lato, this is around 0.75.
  • $ gridRowHeight: Layouts generally rely on default a vertical rhythm to make a nice and consistently spaced reading experience. For example, all elements on a page might be spaced apart in multiples of four or five pixels. We’ll be using 4 as the value because it divides easily into our $ baseFontSize of 16px.
  • $ typeRowSpan: Like $ typeSizeModifier, this variable serves as a multiplier to be used with the grid row height to determine the rule’s line-height value. If our default grid row height is 4 and our type row span is 8, that would leave us with line-height: 32px.

Now we can then plug those numbers into the Basekick formula above (with the help of SCSS functions and mixins) and that will give us the result below.

That’s just what we’re looking for. For any set of text block elements without margins, the two elements should bump against each other. This way, any margins set between the two elements will be pixel perfect because they won’t be fighting with the line box spacing.

Refining our code

Instead of dumping all of our code into a single SCSS mixin, let’s organize it a bit better. If we’re thinking in terms of systems, will notice that there are three types of variables we are working with:

Variable Type Description Mixin Variables
System Level These values are properties of the design system we’re working with. $ baseFontSize
$ gridRowHeight
Font Level These values are intrinsic to the font we’re using. There might be some guessing and tweaking involved to get the perfect numbers. $ descenderHeightScale
$ capHeight
Rule Level These values will are specific to the CSS rule we’re creating $ typeSizeMultiplier
$ typeRowSpan

Thinking in these terms will help us scale our system much easier. Let’s take each group in turn.

First off, the system level variables can be set globally as those are unlikely to change during the course of our project. That reduces the number of variables in our main mixin to four:

$ baseFontSize: 16; $ gridRowHeight: 4;  @mixin basekick($ typeSizeModifier, $ typeRowSpan, $ descenderHeightScale, $ capHeight) {   /* Same as above */ }

We also know that the font level variables are specific to their given font family. That means it would be easy enough to create a higher-order mixin that sets those as constants:

@mixin Lato($ typeSizeModifier, $ typeRowSpan) {   $ latoDescenderHeightScale: 0.11;   $ latoCapHeight: 0.75;      @include basekick($ typeSizeModifier, $ typeRowSpan, $ latoDescenderHeightScale, $ latoCapHeight);   font-family: Lato; }

Now, on a rule basis, we can call the Lato mixin with little fuss:

.heading--medium {   @include Lato(2, 10); }

That output gives us a rule that uses the Lato font with a font-size of 32px and a line-height of 40px with all of the relevant translates and margins. This allows us to write simple style rules and utilize the grid consistency that designers are accustomed to when using tools like Sketch and Figma.

As a result, we can easily create pixel-perfect designs with little fuss. See how well the example aligns to our base 4px grid below. (You’ll likely have to zoom in to see the grid.)

Doing this gives us a unique superpower when it comes to creating layouts on our websites: We can, for the first time in history, actually create pixel-perfect pages. Couple this technique with some basic layout components and we can begin creating pages in the same way we would in a design tool.

Moving toward a standard

While teaching CSS to behave more like our design tools does take a little effort, there is potentially good news on the horizon. An addition to the CSS specification has been proposed to toggle this behavior natively. The proposal, as it stands now, would add an additional property to text elements similar to line-height-trim or leading-trim

One of the amazing things about web languages is that we all have an ability to participate. If this seems like a feature you would like to see as part of CSS, you have the ability to drop in and add a comment to that thread to let your voice be heard.

The post How to Tame Line Height in CSS appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Careful with Nested `display: grid; height: 100%;`

It’s not every day you can feel CSS be slow at something. Reddit user jgbbrd discovered nesting grid containers that all have 100% height can cause many-seconds of rendering delay. Probably not something you’ll ever have to worry about, but still, interesting. From the comments:

  • What a funny use of the NSFW tag!
  • This is not an issue when using 100vh instead.

Direct Link to ArticlePermalink

The post Careful with Nested `display: grid; height: 100%;` appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Animating CSS Width and Height Without the Squish Effect

The first rule of animating on the web: don’t animate width and height. It forces the browser to recalculate a bunch of stuff and it’s slow (or “expensive” as they say). If you can get away with it, animating any transform property is faster (and “cheaper”).

Butttt, transform can be tricky. Check out how complex this menu open/close animation becomes in order to make it really performant. Rik Schennink blogs about another tricky situation: border-radius. When you animate the scale of an element in one direction, you get a squishy effect where the corners don’t maintain their nice radius. The solution? 9-slice scaling:

This method allows you to scale the element and stretch image 2, 4, 6, and 8, while linking 1, 3, 7, and 9 to their respective corners using absolute positioning. This results in corners that aren’t stretched when scaled. 

It’s like the 2020 version of sliding doors.

Direct Link to ArticlePermalink

The post Animating CSS Width and Height Without the Squish Effect appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Fun Tip: Use calc() to Change the Height of a Hero Component

The concept of Fluid Typography was tossed around a couple of years ago. The main idea is that if you know what size your font is at two different viewport sizes, then you can have the font scaling smoothly between the two sizes. We had a jQuery solution for this in FitText (meant of headings, of course) until the calc() function was shipped giving us a pure CSS solution.

p {   font-size: calc(16px + (24 - 16)*(100vw - 400px)/(800 - 400)); }

See the Pen Fluid Typography by Martino Stenta (@martinostenta) on CodePen.

The important numbers here are 24px (the larger font up to 800px viewports) and 16px (the smaller font size down to 400px viewports). I wouldn’t use the terms “minimum” or “maximum” to describe font sizes and viewports in this context because it is a little misleading. In fact, you still need to provide a default font size for viewports smaller than 400px and bigger than 800px — otherwise, the font will keep getting smaller (or bigger) with the same scale of the equation. Or, if you are fancy, you could define another scale for bigger screen sizes.

See the Pen Fluid Typography with reset size by Martino Stenta (@martinostenta) on CodePen.

It works really well and you should definitely check the math behind this.

Padding and line height?

I liked the concept of Fluid Typography so much that I asked myself if it could work with other properties. And it does! You can’t use a percentage, but as long as you stick with px, em or rem units, then it’s OK. I’m a pixel guy, so all my experiments have used those, but there is this neat generatorthat helps you with conversions if you need it.

So, back to padding and line-height. Using the same calc() logic, we can achieve a fully fluid *layout* with fixed values for defined screen sizes.

See the Pen Pure CSS Variable Padding, Font Size and Line Height by Martino Stenta (@martinostenta) on CodePen.

I implemented this idea on this website, but kept it to font-size and line-height. And, yes, it gets easier to look past all that math and put to use the more you work with it.

See the Pen Working Example of calc() on font-size and line-hieght by Martino Stenta (@martinostenta) on CodePen.

A digression about “Hero” components

If you’re like me, then you might take issue with what we all have come to know as the hero component. It’s ubiquitous to the extent that it’s become a staple in design systems (like Bootstrap) and you may have even seen it satirized on sites like this.

My main gripe concerns the best way to make them responsive. If it’s not a *full screen* hero (i.e. takes over the entire viewport at any size), then I usually ask the designer how the page should behave. There’s often a proportion of the hero page that works fine, so that allows me to use padding-bottom in % with absolute positioning of the inner content. That tactic works most of the time,

This is fun and it works fine especially on the desktop version of a website. You end up with a neat hero section, the proportion is good and the content is centered.

See the Pen Standard hero section with ‘padding-bottom’ by Martino Stenta (@martinostenta) on CodePen.

But what happens when you start shrinking the viewport? The hero remains readable up to a point, you really need to change the proportion.

Assuming we are working with a desktop-first responsive approach, we could start with a horizontal rectangle that scales down to the point where we’re left with a vertical rectangle on small screens.

Hero component with different proportions based on device

This is a PITA because you could end up with many lines of CSS to have a nice and readable hero section at various breakpoints.

There has to be a better way, right? What if the hero could increase its height while the page width gets narrower?

Back to fluidity!

So, I turned back to the calc() function that worked in those other situations, like making the browser handle the math and scale things accordingly as the viewport changes.

Here’s the CSS from the Fluid Typography example we started with:

p {   width: 100%;   max-width: 1200px;   margin: 0 auto;   font-family: 'Open Sans', sans-serif;   font-size: calc(24px + (18 - 24)*(100vw - 400px)/(1200 - 400));   line-height: 1.5;   padding: 10px; }

Here’s what we want: a hero component that gets bigger while you shrink the page. I used pixel units for the fluid part and percentages everywhere else.

Here’s a screencast of how the solution I landed on:

Live Demo

This is pretty useful when you want to give more vertical space to the text. Shrinking the viewport width from large to small will end up having more lines for the same text, since the font size can’t be too small.

See the Pen Hero section with calc() by Martino Stenta (@martinostenta) on CodePen.

Pretty nice, right? Yet another way calc() proved it could solve a scenario for me.

Yes, there are some caveats

Browser support is very good, tallying almost 93% of the users (at the time of writing), with the main exception being Opera mini.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
19* 15 4* 10 12 6*

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
6.0-6.1* 46 No 67 69 62

Also, remember that this calc() technique supports only px, em, and rem units. But the examples we covered here are pretty easy to convert units for things like padding-bottom percentages to pixels since the hero is typically 100% in width.

Oh! And remember to reset your values before and after the breakpoints in the calc() function. Otherwise you’ll end up with either very big or very small values for the target properties.

What say you?

This is probably just one way we can handle the situation and it was primarily driven by my interest in the calc() function. So, that begs the question: how have you handled scaling hero component height? Have you put calc() to use for it? Do you prefer wrangling breakpoints at various widths? Is there something else you use? Light up the comments!

The post Fun Tip: Use calc() to Change the Height of a Hero Component appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]