Picture of a blue and yellow building, by William Daigneault

Last week we were talking about pseudo-elements and pseudo-classes in CSS. In that post, we saw how these CSS features allow us to generate more concise, intelligible, and easy-to-maintain code. Today I would like to share with you some additional CSS properties to build adaptive websites that take into account the preferences of your visitors.

Aspect Ratios with object-fit and object-position

object-fit is a CSS property that allows you to set how a replacement element (for example an image) should be resized to fit its container. Let’s see what this means with a concrete example, shall we?

Suppose we have the following vertical image:

Image of a woman looking at an urban landscape
Image of woman looking at an urban landscape. Photograph by Elvis Ma on Unsplash.

and we want to display it in within the following area:

which is 15em high and takes 80% of the available width. In principle, you might think that all we have to do is set a specific width and height to our image, right?

.custom-size {
  height: 15em;
  width: 80%;
}

Well, if you do, you’ll see that the image’s aspect ratio is messed up:

Stretched image because of an aspect ratio other than the original's

To prevent an image from being distorted when using specific width and height, developers used to rely on (and some still do) the CSS background property of a div. So, instead of adding the image using the img tag, we used to create a div container:

<div id="custom-image"></div>

set the correct dimensions to said div, and then add the actual image via CSS using the background-size and background-position properties:

#custom-image {
  background-image: url( …/image.jpg );
  background-size: cover;
  background-position: center;
  height: 15em;
  width: 80%;
}

And here you can see the result:

Scaling and cropping images by using CSS background properties on a div tag is a bad solution, because you’re no longer using the semantically correct HTML tag: img. Besides, img tags include a bunch of cool properties that will result in faster and more accessible websites: an alt property that describe the image, srcset to make it responsive, loading to lazy load it, and so on.

If you want to scale and crop an image so that it fits some specific dimensions without distorting the image itself, all you have to do is use the object-fit and object-position CSS properties, which behave as background-size and background-position do:

.custom-size {
  height: 15em;
  object-fit: cover;
  object-position: center;
  width: 80%;
}

If you apply the previous rules to an img tag:

<img class="custom-size" src="…/image.jpg" />

this is the result you get:

Cropped (but not stretched) image when using an aspect ratio other than the original's

which is exactly what you were interested in, weren’t you?

If you want to know more about this property, here is a link with all the necessary information.

Adaptive Design with Media Queries

Media queries are a mechanism that allows you to add CSS rules to your website based on the characteristics of the device or application from which your visitors access the web. I’m quite sure you’re somewhat familiar with them, as media queries are the basis for building responsive websites, but there’s a lot more you can do with them!

Classic Media Queries

Using a media query in a CSS stylesheet is as easy as adding the @media keyword with two things: on the one hand, a condition that describes when the media query is active and, on the other hand, the set of CSS rules that should be loaded when the condition is met. That’s why media queries are the basis for building responsive designs: you simply apply one set of rules or another depending on the width of the visitor’s browser.

For example, let’s assume you want to change the following paragraph’s sidebar:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. The lion on the porch soft ugly sometimes, but quiver outdoor element. But the need for entrepreneurs called thermal stress. Reserved microwave, but my door is always or sometimes mass author. Android and Nunc sodales interdum, tincidunt erat ac, tincidunt elit. However, ultricies ac, arcu metus Sed congue. For convenience fear leo enhanced protein. Is a tellus orci, tempor id egestas nec, at least get some players.

so that it uses all the colors in the rainbow depending on the width of the browser. Here’s how you can achieve this behavior via CSS:

.colored-border {
  border-left: 0.5em solid red;
  padding-left: 1em;
}
@media ( min-width: 400px ) {
  .colored-border {
    border-color: orange;
} }
@media ( min-width: 600px ) {
  .colored-border {
    border-color: yellow;
} }
@media ( min-width: 800px ) {
  .colored-border {
    border-color: green;
} }
@media ( min-width: 1000px ) {
  .colored-border {
    border-color: cyan;
} }
@media ( min-width: 1200px ) {
  .colored-border {
    border-color: blue;
} }
@media ( min-width: 1400px ) {
  .colored-border {
    border-color: violet;
} }

Quite easy, right? We simply need to apply a different color every time the width of the browser is over a certain threshold. Note that we implement this using a mobile first approach, because “new” rules are applied as the screen gets bigger. Change the width of the window and you’ll see the result.

How to Implement the Dark Mode with CSS

Dark modes are trendy now, both on mobile and desktop. Did you know that there is a media query to see if users prefer dark modes? Using the media query prefers-color-scheme you can see if the user prefers a light color scheme or dark one. Which means you now have the power to build two versions of your website so that it matches the preferences of all your visitors.

For instance, consider the following HTML snippet:

<div class="force-light-theme">Light Theme</div>
<div class="force-dark-theme">Dark Theme</div>
<br>
<div class="theme">Dynamic (based on your settings)</div>

and these CSS rules:

.force-light-theme { background: #eee; color: black; }
.force-dark-theme { background: #333; color: white; }
@media (prefers-color-scheme: light) {
  .theme { background: #eee; color: black; }
}
@media (prefers-color-scheme: dark) {
  .theme { background: #333; color: white; }
}

Depending on your setup, you’ll see that the “Dynamic” part of the previous HTML snippet either looks like the Light Theme or the Dark Theme:

Light Theme
Dark Theme

Dynamic (based on your settings)

Pretty cool, huh? And simple!

Other Interesting Use Cases with Media Queries

There are a lot of media queries you can use (you have a complete list here), but I would like to focus on one in particular. Specifically, I want to explain to you how to apply different styles depending on whether the page is displayed in the browser or is about to be printed. All you have to do is use the print or screen keyword to the media query as follows:

@media print { … }
@media screen { … }

or create two separate CSS files, one for each use case, and include them in your HTML using the media property of a link tag:

<link media="print" src="…/print.css" />
<link media="screen" src="…/default.css" />

The interesting thing about this is that you can create a stylesheet that transforms your site into a piece of content that’s designed to be printed. Thus, for example, you’d be able to hide dynamic parts of the web that don’t make sense in a printed version (like menus or forms). Or you can even make sure some things that are lost when printed become visible, such as for example the target URL of a link:

@media print {
  .menu {
    display: none;
  }
  .show-links a:after {
    content: " (" attr(href) ")";
  }
}

whose result is the following:

CSS Variables

Finally, let’s talk about another amazing CSS feature: CSS custom properties (also known as CSS variables). Complex websites have very large amounts of CSS, and it’s quite common to have the same value repeated over and over again. For example, your color palette, borders, paddings, and so on are used all over the place. Well, CSS variables simplify this complexity. And they are extremely useful for implementing dark mode easily!

CSS variables are exactly what you’re thinking: a way to store and reuse a specific CSS value behind a name that’s meaningful. It’s way easier to understand what --main-text-color is than #333, isn’t it?

Declaring a custom property is done using a custom property name that begins with a double hyphen (--), and a property value that can be any valid CSS value. Like any other property, this is written inside a ruleset, like so:

element {
  --main-color: red;
  --main-padding: 2em 1em;
}

The selector you use in the rule block where you have defined the CSS variable determines its scope. That is, if you define a variable within a div.banner rule, that variable will only be available in that scope. However, the most common is to create variables in the global scope using the pseudo-class :root :

:root {
  --main-color: red;
  --main-padding: 2em 1em;
}

In order to use a CSS variable, you simply need to specify its name inside the var function:

p {
  color: var(--main-color);
  padding: var(--main-padding);
}

CSS is Here to Help You

The HTML structure of a web page is like the foundation of a house―you need a solid foundation if you want to build something sound. When creating a web page, make sure you use a semantically correct and clean HTML tree. This will result in a page that will work on all browsers for all visitors, and applying CSS tricks on top of it will be simple and effective.

I hope you liked today’s post. If you did, share it with your friends 😉

Featured image by William Daigneault on Unsplash.

Leave a Reply

Your email address will not be published. Required fields are marked *

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.