Implementing a consistent CSS structure for various media sizes

Utilizing CSS grid and Sass, I implement varying grid layouts for different screen sizes (phone, tablet, desktop). However, on certain pages, I desire the same layouts at slightly larger or smaller screens than others.

Is there a way to achieve this without duplicating styles excessively? My current solution (shown below) functions, but results in repetitive styling.

To elaborate:

I have 3 distinct grids selected according to screen size.

.hero {
    &__container {
        grid-template-areas:
            "header"
            "image"
            "text";
        }
        @media min-width: 1000px {
            grid-template-areas:
                "header header header"
                "text   ...     image"
                "text   ...     image";
            }
            // additional definitions for this screen size
        }
        @media min-width: 1300px {
            grid-template-areas:
                "header header image"
                "text   ...    image"
                "text   ...    image";
            }
            // other definitions for this size
        }
    }

  &__header {
    grid-area: header;
    font-size: 2.5rem;
    
    @media min-width: 1000px {
        font-size: 2.8rem;
    }
    @media min-width: 1300px {
        font-size: 3.2rem;
    }
  }
  ...
}

These are utilized across approximately 20 similar web pages.

<div class="page_a">
    <div class="hero">
        <div class="hero__container">
            <div class="hero__header">...</div>
            <div class="hero__text">...</div>
            <div class="hero__image">...</div>
        </div>
    </div>
</div>

The layout remains consistent, however, I wish to transition to different layouts at varying breakpoints based on content specifics like header text length, image size, importance, etc.

What I aim to accomplish is depicted as follows:

.page_a {
    .hero {
        // retain default settings, no alterations
    }
}

.page_c {
    .hero {
        // longer header requires bigger screen for largest layout switch 
        // specify that the 1300px layout should be used from 1500px
    }
}

The sole workaround I achieved was merely redefining all the grids at each potential breakpoint (default + custom ones), leading to excessive repetition in the code:

.page_c {
    .hero {
        // utilize 1000px layout also for 1300px - whole process needs to be repeated
        @media min-width: 1300px {
            grid-template-areas:
                "header header header"
                "text   ...     image"
                "text   ...     image";
            }
            // additional definitions for this size
        }
        // use 1300px layout for 1500px - entire set of rules has to be reiterated
        @media min-width: 1500px {
            grid-template-areas:
                "header header image"
                "text   ...    image"
                "text   ...    image";
            }
            // other specifications for this size
        }
    }
}

This implies that whenever a layout adjustment is made, changes must be applied throughout all instances where it is used at various sizes.

Answer №1

Consider using SASS or SCSS along with a @mixin to solve your issue. I personally prefer SCSS, but you can also use SASS.

Understanding the @mixin

According to the official SASS documentation:

Mixins enable you to define styles that are reusable throughout your stylesheet.

To utilize a @mixin, first define it and then call it in your code using an @include. Each @mixin should have a distinct name. For instance, create a @mixin layout_600 and employ it with an @include layout_600.

There are two key considerations when working with @mixin:

  1. Define a @mixin before utilizing it with an @include. Otherwise, SCSS will attempt to call something undefined as it's declared later in your stylesheet.
  2. Declare a @mixin outside of your nested code (preferably at the top of your stylesheet). If you define a @mixin within nested code, you won't be able to reference it later for modifying default styles. To understand this concept better, let me show you the right way versus the wrong way.

Correct Approach:

@mixin layout_600 {
    font-size: 3rem;
    color: blue;
    font-weight: 700;
}

.hero {
    &__header {
        @media (min-width: 600px) {
            @include layout_600;
        }
    }
}

.page_b {
    .hero {
        // Using the 600px layout for 1000px width as well
        &__header {
            @media (min-width: 1000px) {
                // This works successfully
                @include layout_600;
            }
        }
    }
}

Incorrect Approach:

.hero {
    &__header {
        @media (min-width: 600px) {
            @mixin layout_600 {
                font-size: 3rem;
                color: blue;
                font-weight: 700;
            }
        }
    }
}

.page_b {
    .hero {
        // Using the 600px layout for the 1000px as well
        &__header {
            @media (min-width: 1000px) {
                // This won't work
                @include layout_600;
            }
        }
    }
}

For each desired layout (e.g., 600px), create a @mixin. You only need to define it once per layout, but you can invoke a particular @mixin multiple times. This has several advantages:

  • No need to rewrite your code, simply call the specific @mixin with @include whenever needed.
  • If style modifications are required, update the @mixin once. The changes will reflect across all references to that @mixin.

Demonstration Example

Prior to Default Style Alteration

I defined three @mixins like so:

  • for window width < 600px,
  • for 600px < window width < 1000px and
  • for window width > 1000px.

https://i.stack.imgur.com/dC7Qw.png

The font-size and color vary based on different window widths. Font size increases and color transitions from black to blue to red as window width expands. Additionally, there's a div in the top right corner displaying current window width.

Post Default Style Modification

I opted to utilize the 600px layout (@mixin layout_600) for page_b even at 1000px. Achieving this is simple by calling @mixin layout_600 via @include layout_600 as shown below:

.page_b {
    .hero {
        // Applying 600px layout for 1000px width as well
        &__header {
            @media (min-width: 1000px) {
                @include layout_600;
            }
        }
    }
}

https://i.stack.imgur.com/vmTWf.png

In the scenario where window width actually reaches 1000px, the styling for page_b mirrors that of 600px width (smaller font and blue color).

Customizing a @mixin

You can also customize a @mixin if necessary. For example, I utilized the 600px layout (@mixin layout_600) but altered the color from red to green as illustrated below:

.page_b {
    .hero {
        // Applying 600px layout for 1000px width as well
        &__header {
            @media (min-width: 1000px) {
                @include layout_600;
                color: green; // Customizing the mixin
            }
        }
    }
}

https://i.stack.imgur.com/NkYdf.png

As evident, the color should've been blue (as dictated by @mixin layout_600), but it appears green instead.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm wondering if there is a method for me to get only the count of input fields that have the class "Calctime" and are not empty when this function is executed

Currently, I am developing an airport application that aims to track the time it takes to travel between different airports. In this context, moving from one airport to another is referred to as a Sector, and the duration of time taken for this journey is ...

Tips for updating the css class for multiple DOM elements using jQuery

I am currently attempting to modify the class property of a specific DOM element (in this case, a label tag) using jQuery version 1.10.2. Here is the code snippet I have written: var MyNameSpace = MyNameSpace || {}; MyNameSpace.enableDisableLabels = (f ...

Poor mapping on Google Maps API

I've been trying to embed a Google Maps on my website, but for some reason, it keeps stretching and showing grey sections with rounded borders. Here's the code I'm using: <div class="p-5 col-6 d-flex flex-column justify-content-between"& ...

Ensure that the initial section of the page spans the full height of the browser, while all subsequent sections have a

I have a website composed of various blocks with different heights, all extending to full width. My goal is to make the first block the full height and width of the browser window, while keeping the other blocks at a set height as seen on this site: After ...

What methods can I use to make sure the right side of my React form is properly aligned for a polished appearance?

Trying to create a React component with multiple input field tables, the challenge is aligning the right side of the table correctly. The issue lies in inconsistent alignment of content within the cells leading to disruption in overall layout. Experimente ...

Dynamic mouse path

Currently, I am in the process of creating a mouse trail similar to what is found on this particular website. I have been using JavaScript, jQuery, and various libraries in my attempt to achieve this effect; however, it has proven to be more challenging th ...

The dimensions of the background for a span element

I have a span element with a background-color applied to it. Is there a way to adjust the size of this specific background? I attempted using background-size: auto 2px;, but it did not produce the desired effect. I am looking to make the background color ...

Display an image when the link is hovered over within a table

I'm looking for a way to display a scanned receipt image when hovering over a link within a table. I've written some code but it's not working as expected. Can anyone help me figure out what's wrong? Here is the current state of my cod ...

Encountered a problem while attempting to create two separate div elements. The template root is designed to have only one element. This issue

<template> <div class="footerpart-container"> <div class="general-container"> dadada </div> <div class="legal-container"> dadad </div> <div class="helpsupport-container"> dada ...

How can I make my image shine when the mouse hovers over

I have recently come across a fascinating effect where an image glows up when the mouse hovers over it. This is not your typical border glow, but rather a unique enhancement of colors within the image itself. I discovered a library called Pixastic that can ...

Unable to make the Show/Hide Loading GIF function work as intended

Could someone please help me with my code? I'm trying to display a loading GIF image while waiting for an ajax request to complete. When the button is pressed, I want the loader to be shown until the data is returned from the server. I would greatly ...

What is the correct way to center-align elements?

I have a basic grid layout that has been styled using CSS. #videowall-grid{ width:700px; border:1px dotted #dddddd; display: none; margin: 5px auto; padding: 5px; } #videowall-grid .square{ padding: 5px; margin: 5px; bo ...

Specify the height of a div tag based on a certain condition

I'm trying to style a div tag in a specific way: If the content inside the div is less than 100px, I want the div tag's height to be exactly 100px. However, if the content's height exceeds 100px, I want the div tag's height to adjust au ...

1. "Customizing Navbar height and implementing hover color for links"2. "Tips for

Having issues adjusting the height of my Navbar - when I try to do so, the collapse button doesn't function properly. I've attempted setting the height using style="height: 60px;" and .navbar {height: 60px;} but the collapse menu stops ...

"Step-by-step guide on placing an order for the button

I am currently working with material-ui and encountering a roadblock. My goal is to design a homepage for a dashboard where the various services are listed. I am attempting to organize these 6 buttons into 2 rows and 3 columns, totaling 6 buttons in all. A ...

Streamlined Boilerplate to Kickstart Your Project

Can anyone suggest a well-crafted boilerplate .less file to kickstart a new project? I'm looking for a comprehensive .less file that includes: CSS Resets styles CSS Normalizer styles CSS3 Helpers (box radius, gradients, box shadow, transition) Basic ...

What is the best way to continuously loop the animation in my SVG scene?

After designing a SVG landscape with an animation triggered by clicking the sun, I encountered an issue where the animation only works once. Subsequent clicks do not result in any animation. Below is my current JavaScript code: const sun = document.getEle ...

Expanding div that adjusts to content size and expands to fit entire page

Appreciate your help. I'm currently facing an issue with the "content" and "footer" sections within the "wrapper" element. Below are the styles for these elements: #content { width: 100%; min-height: 100%; position: relative; background- ...

How to Make a Div Tag Fade Effect with JavaScript in an External File

*** New Team Member Notice *** I'm currently working on an assignment and trying to implement a simple fade effect on a box. While it seems like this should be straightforward, I'm encountering some obstacles. Currently, the button causes the bo ...

How can I remove a specific JSON object from localStorage based on the data associated with the element that is currently being clicked on?

Unique Scenario A user interacts with an element, triggering a change in the background image and storing data related to that element in localStorage: this process functions correctly. Next, the toggle variable is set to 0, the background image change ...