CSS Viewport Units for Fast Layout

CSS Viewport Units for Fast Layout

CSS Viewport units have been around for the past few years, and as time goes by, more and more developers are starting to use them. The benefit of these is that they provide us with a way to resize in a dynamic way without the need for JavaScript. And if it fails, there are plenty of backup plans.

In this article, we will learn about CSS Viewport units and how to use them, and then we will look at some common problems and their solutions and use cases. Let’s get started.

Introduction

According to the CSS specification, viewport percentage units are relative to the size of the initial containing block, which is the root element of the web page.

The viewport units are: vw , vh , vmin , and vmax .

The vw unit represents a percentage of the root element's width. 1vw is equal to 1% of the viewport width.

Viewport Width

The vw unit represents a percentage of the root element's width. 1vw is equal to 1% of the viewport width.

Suppose we have an element with the following CSS:

.element {
    width: 50vw;
}

When the viewport width is 500px , 50vw is calculated as follows

width = 500*50% = 250px

Viewport Height

The vh unit represents a percentage of the root element's height; one vh is equal to 1% of the viewport's height.

We have an element with the following CSS:

.element {
    height: 50vh;
}

When the viewport height is 290px , 70vh is calculated as follows:

height = 290*70% = 202px

Everyone says that there is no project in their resume, so I found a project for everyone and also attached a [construction tutorial].

Vmin Unit

vmin represents the smaller value of the width and height of the viewport, that is, the smaller value of vw and vh . If the viewport width is greater than its height, the value will be calculated based on the height.

Let’s take the following example.

We have a landscape phone with an element that has a vmin unit. In this case, the value will be calculated based on the viewport height since it is smaller than the width.

.element {
    padding-top: 10vmin;
    padding-bottom: 10vmin;
}

This is how vmin is calculated:

As you might guess, the calculations are as follows

padding-top = (10% of height) = 10% * 164 = 16.4px 
 
padding-bottom = (10% of height) = 10% * 164 = 16.4px

Vmax Unit

vmax is the opposite of vmin , and is the larger value of vw and vh .

Let’s take the following example.

.element {
    padding-top: 10vmax;
    padding-bottom: 10vmax;
} 

The calculation results are as follows:

padding-top = (10% of width) = 10% * 350 = 35px 
padding-bottom = (10% of width) = 10% * 350 = 35p

How do viewport units differ from percentages?

Viewport units are based on the root element of the page, while percentages are based on the container they are in. Therefore, they are different from each other, but each has its own uses.

Use case font size in viewport units

CSS viewport units are great for responsive typography. For example, we could use the following as our article title:

.title {
    font-size: 5vw;
}

font-size of the title will increase or decrease depending on the viewport width. It's like providing a font size that is 5% of the viewport width. However, using it without proper testing can lead to pitfalls. Let's watch the video below:

The body size becomes very small, which is not good for accessibility and user experience. As far as I know, the minimum font size on mobile devices should not be less than 14px . In GIF, no smaller than 10px .

To solve this problem, we need to provide a minimum font size for the title, which we can do using calc()

.title {
    font-size: calc(14px + 2vw);
}

calc() CSS function will have a minimum value of 14px and add a value of 2vw to that. With this, the font-size values ​​won’t get too small.

Another important thing to consider is how the font size behaves on larger screens, such as 27” iMac . What happens? You guessed it, the font size is around 95px , which is a large value. To prevent this, we should use media queries and change the font size at certain breakpoints.

@media (min-width: 1800px) {
    .title {
        font-size: 40px;
    }
}

By resetting the font size we can ensure that the size doesn't get too big. You may also need to add multiple media queries, but that’s up to you and depends on the context of your project.

Example address: https://codepen.io/shadeed/pen/fa989837c6379770cce49f0be6daa3e3

full screen

Sometimes, we need a p to get 100% of the viewport height. For this, we can use viewport height unit.

.p {
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

By adding height: 100vh , we can ensure that p height will take 100% of the viewport. Additionally, we added some flexbox to handle centering the content horizontally and vertically.

Example source code: https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=1100

Sticky layout (footer)

On large screens, the website content is sometimes sparse and footer doesn’t stick to the bottom. This is normal and not considered a bad practice. However, there is room for improvement. Consider the following diagram that represents the problem:

To fix this, we need to give the content a height that is equal to the viewport height - (header + footer) . It's difficult to do this dynamically, but using CSS's viewport, it's easy.

First solution: calc and viewport units

If the height of header and footer is fixed, you can combine calc() function with viewport units, like this:

header,
footer {
    height: 70px;
}
 
main {
    height: calc(100vh - 70px - 70px);
}

This solution is not guaranteed to always work, especially于footer . In my career I have not used a fixed height footer because it would not be feasible at different screen sizes, for example.

2. Second solution: Flexbox and viewport units ( recommended )

By setting 100vh as the height of body element, you can then use flexbox to make main element take up the remaining space.

body {
    min-height: 100vh;
    display: flex
    flex-direction: column;
{
 
main {
    /* This will make the main element take the remaining space dynamically */
    flex-grow: 1;
}

This way, the problem is solved and we have a sticky footer regardless of the content length.

Example source code: https://codepen.io/shadeed/pen/c735b26b8fa97ee685b38084448b3f85?editors=1100

Responsive elements

Let’s say we have a portfolio showcasing our responsive design work and we have three devices (mobile, tablet, and laptop). Each device contains one image. The goal is to use CSS to responsively adapt these pages.

By using CSS Grid and viewport units we can make it fully dynamic and responsive.

<div class="wrapper">
  <div class="device laptop"></div>
  <div class="device mobile"></div>
  <div class="device tablet"></div>
</div>

Viewport units can also be used in grid- * properties, but also in border , border-radius and other properties.

.wrapper {
  display: grid;
  grid-template-columns: repeat(20, 5vw);
   grid-auto-rows: 6vw;
}
 
.mobile {
   position: relative;
  z-index: 1;
  grid-column: 2 / span 3;
  grid-row: 3 / span 5;
}

 .tablet {
  position: relative;
  z-index: 1;
  grid-column: 13 / span 7;
   grid-row: 4 / span 4;
  border-bottom: 1vw solid #a9B9dd;
  border-right: solid 3vw #a9B9dd;
}

 .laptop {
  position: relative;
  grid-column: 3/span 13;
  grid-row: 2 / span 8;
}
 
/* Viewport units are used for the bottom, left, right, height, and border-radius. Isn't that cool? */
.laptop:after {
    content:"";
    position:absolute;
    bottom: -3vw;
    left: -5.5vw;
    right: -5.5vw;
    height: 3vw;
    background-color: #a9B9dd;
    border-radius: 0 0 1vw 1vw;
} 

Example source code: https://codepen.io/shadeed/pen/2da0f2b70699769f8de3220ff4465bc6?editors=1100

Break free from the container

I noticed one use case that works best for editing layouts. A child element that takes up 100% of the viewport's width, even if the parent element's width is constrained. Consider the following:

.break-out {
    width: 100vw;
    position: relative;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
}

Let's break it down a bit so we can understand, bit by bit, how all of these properties work.

1. Add width: 100vw

The most important step is to set the width of the image to 100% of the viewport.

2. Add margin-left: -50vw

To center the image, we need to give it a negative margin with a width of half the viewport width.

3. Add left: 50%

Finally, we need to push the image to the right by a value of 50% of the parent width.

Example address: https://codepen.io/shadeed/pen/828f12b1ef7fa7211584ff5c7b82d2fa?editors=1100

Vertical and horizontal spacing

Another interesting use case that comes to mind is using viewport units to represent spacing between elements. This can be used in conjunction with values ​​such as margin , top , bottom , and grid-gap . When used, the spacing will be based on the viewport width or height, which may be useful for making your layout more dynamic.

Modal Box

For modals, we need to push them in from the top of the viewport. Typically, you do this with top property, and use either a percentage or a pixel value. However, with viewport units we can add a spacing that can change based on the viewport height.

.modal-body {
    top: 20vh;
}

Example address: https://codepen.io/shadeed/pen/f77a0d58947c64c2b3dadbd887700db5?editors=1100

Page Header

The page header is the part that serves as the introduction of the page. It usually has a title and description, and has fixed height or padding on the top and bottom edges.

For example, given the following CSS style:

.page-header {
    padding-top: 10vh;
    padding-bottom: 10vh;
}
 
.page-header h2 {
    margin-bottom: 1.5vh;
}

Use vh units for padding of the page title, and for the margin below the title. Notice how the spacing changes!

Example source code: https://codepen.io/shadeed/pen/43024fa031519e316e95bb3ce47f2b22?editors=1100

Vmin and Vmax Use Cases

This use case is about top and bottom padding of page title element. When the viewport is smaller (mobile), padding is usually reduced. By using vmin , we can get the appropriate top and bottom padding based on the smaller dimension of the viewport (width or height).

.page-header {
    padding: 10vmin 1rem;
} 

Example source code: https://codepen.io/shadeed/pen/f335c2f43b960a2c70ea057228ddc5b9?editors=0100

Aspect Ratio

We can use vw units to create responsive elements that maintain their aspect ratio regardless of the viewport size.

First, you need to determine the aspect ratio you want, for this example, use 9/16 .

p {
    /* 9/16 * 100 */
    height: 56.25vw;
} 

Example source code: https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=0100

Popular top border

You know that top border that most websites use? Often, it’s the same color as the brand’s, which lends it some personality.

We support an initial value of 3px for the border. How to convert fixed value to viewport object? Here's how to calculate its vw equivalent.

vw = (Pixel Value / Viewport width) * 100

The viewport width is used to estimate the ratio between pixel values ​​and required vw units.

For our example, we add the following styles to header :

.header {
    border-top: 4px solid #8f7ebc;  
}

In my case the viewport width is 1440 (this is not a fixed number, please replace it with your own)

vw = (4 / 1440) * 100 = 0.277
.header {
    border-top: 0.277vw solid #8f7ebc;  
}

Even better, we can use a base pixel value, and the viewport unit can be additive.

.header {
    border-top: calc(2px + 0.138vw) solid $color-main;
}

Mobile scrolling issues

There is a common problem in mobile devices that even with 100vh , there will be scrolling because the height of the address bar is visible. Louis Hoebregts wrote an article about this problem and gave a simple solution.

.my-element {
  height: 100vh; /* Fallback for browsers that don't support custom properties */
  height: calc(var(--vh, 1vh) * 100);
}
// First, we get the viewport height, which we multiply by 1% to get a value in vh units let vh = window.innerHeight * 0.01;
// Then, set the value in the `--vh` custom property to a property in the document's root directory document.documentElement.style.setProperty('--vh', `${vh}px`); 

Example source code: https://codepen.io/shadeed/pen/1d18ca2d23ec0038c759dc62dc3fd8c3?editors=0110

This is the end of this article about how to use CSS Viewport units to achieve fast layout. For more relevant CSS Viewport unit content, please search 123WORDPRESS.COM’s previous articles or continue to browse the following related articles. I hope that everyone will support 123WORDPRESS.COM in the future!

<<:  Solution to index failure caused by MySQL implicit type conversion

>>:  Usage and principles of provide and inject in Vue3

Recommend

Implementation principle and configuration of MySql master-slave replication

Database read-write separation is an essential an...

MySQL character set garbled characters and solutions

Preface A character set is a set of symbols and e...

A brief discussion on using Vue to complete the mobile apk project

Table of contents Basic Configuration Entry file ...

How to write a MySQL backup script

Preface: The importance of database backup is sel...

Detailed explanation of data type issues in JS array index detection

When I was writing a WeChat applet project, there...

Implementation of Docker deployment of SQL Server 2019 Always On cluster

Table of contents Docker deployment Always on clu...

Two methods of restoring MySQL data

1. Introduction Some time ago, there were a serie...

JavaScript design pattern learning proxy pattern

Table of contents Overview Implementation Protect...

Methods and steps for Etcd distributed deployment based on Docker

1. Environmental Preparation 1.1 Basic Environmen...

How does MySQL ensure data integrity?

The importance of data consistency and integrity ...

SQL implementation of LeetCode (175. Joining two tables)

[LeetCode] 175.Combine Two Tables Table: Person +...

A brief talk about JavaScript Sandbox

Preface: Speaking of sandboxes, our minds may ref...

Detailed explanation on how to deploy H5 games to nginx server

On the road to self-learning game development, th...