Now Reading
Rebuilding a featured information part with fashionable CSS: Vox information

Rebuilding a featured information part with fashionable CSS: Vox information

2023-04-30 09:55:55

Taking a look at a structure at first look may indicate that it’s simple and easy to construct. The second you begin constructing the preliminary structure, you’ll face challenges that you simply didn’t take into consideration in your preliminary take a look at the design.

On this article, I’ll rethink how you can construct the featured information part on Vox.com and attempt to see if fashionable CSS will probably be useful or not. For instance, do we have to use container queries? Or fluid sizing? That’s the objective of this text. It’s a journey as I feel aloud about constructing a structure that appears easy.

Desk of contents

Analyzing the part

Within the largest viewport, we’ve a 3 columns structure. Two of the columns take 25% of the width, and the center one takes 50%. Here’s a visible that reveals them:

Now that we’ve an thought concerning the columns, let’s check out the parts inside them.

It’d look a bit complicated to identify the variations, however I’ll stroll you thru every change so we will have an thought about what’s altering on every viewport measurement.

Adjustments from the big to medium

  • Featured part: virtually the identical, however with a distinct font measurement that’s altering based mostly on the viewport width.
  • Blue part: the font measurement of every card title received smaller.
  • Pink part:
    • The primary article’s thumb is hidden.
    • Structure is modified from one column to 3 columns.
    • Including a separator on the high of the part.

Adjustments from medium to small

  • All articles will swap to the horizontal fashion with the thumbnail proven for each.
  • The featured article will turn into horizontal, however with a bigger thumbnail to distinguish it from the remainder of the articles.

With that in thoughts, we’ve a primary define of how the structure is behaving on completely different viewport sizes. The following step is to construct the structure and deal with the ordering of the columns.

Constructing the principle structure

In vox.com, CSS flexbox is getting used to deal with the structure. I’m not a fan of utilizing flexbox for such a function as this feels extra like a CSS grid use case. I imagine the Vox crew used flexbox because it was higher supported on the time of constructing the structure.

@media (min-width: 880px)
    .c-newspaper__column {
        width: 22.5%;
        padding: 0 16px;
    }
}

The CSS above is accountable for the next:

  • Setting the width of the column. Utilizing width property for that works positive, however we will additionally use the flex property.
  • Including padding on the left and proper sides is an previous technique to introduce a niche between columns. Now we’ve the hole property!

We are able to use the flex property like this:

@media (min-width: 880px)
    .c-newspaper__column {
        flex: 0 0 22.5%;
        padding: 0 16px;
    }
}

..however the excellent news is that we don’t have to make use of flexbox.

These days, CSS grid has wonderful browser assist and it’s simpler to cope with the sizing and spacing. Additionally, I’m an advocate of utilizing grid for layouts and flexbox for components.

Take into account the next HTML markup:

<div class="c-newspaper">
    <!-- Featured column -->
    <div class="c-newspaper__col">1</div>
    
    <!-- Different columns -->
    <div class="c-newspaper__col">2</div>
    <div class="c-newspaper__col">3</div>
</div>

I added numbers for illustrating how every structure column will probably be reordered on completely different viewport sizes.

CSS grid sounds good for the above, proper?

First, we have to arrange the grid for all sizes.

.c-newspaper {
    show: grid;
    grid-template-columns: 1fr;
    hole: 1rem;
}

@media (min-width: 550px) {
    .c-newspaper {
        grid-template-columns: 1fr 1fr 1fr;
    }
}

@media (min-width: 880px) {
    .c-newspaper {
        grid-template-columns: 1fr 2fr 1fr;
    }
}

Just a few issues to remember:

  • Initially, the grid has just one column. I used CSS grid to get the advantage of the hole property for spacing.
  • When the viewport width is 550px or bigger, the grid could have 3 columns. The identical occurs on the bigger viewport 880px, however the second column is double the scale of its sibling columns.

The vox.com types for the columns are constructed with the order property to reposition the columns on completely different sizes.

@media (min-width: 880px) {
    .c-newspaper__column:first-child {
        order: 1;
    }
    
    .c-newspaper__column:last-child {
        order: 3;
    }
}

With CSS grid, the above isn’t wanted in any respect as we will reorder the structure by positioning a component on any grid traces we would like.

Let’s discover how you can place the structure columns with CSS grid.

The medium viewport measurement

We have to place the columns as per the viewport width. For the medium measurement:

  • The primary column is positioned from line 2 to line 4.
  • The second column is positioned from line 1 to line 2.
  • The third column is positioned from line 1 to line 4 (spanning the total width).
@media (min-width: 550px) {
    .c-newspaper {
        grid-template-columns: 1fr 1fr 1fr;
    }
    
    .c-newspaper__col:first-child {
        grid-column: 2/4;
    }
  
    .c-newspaper__col:nth-child(2) {
        grid-column: 1/2;
        grid-row: 1;
    }
  
    .c-newspaper__col:last-child {
        show: flex;
        grid-column: 1/4;
    }
}

The big viewport measurement

And for the big measurement, do not forget that the second column is now 2fr, so it must double the scale of the facet column.

  • The primary column is positioned from line 2 to line 3.
  • The second line stays inside the similar placement.
  • The final column is positioned from line 3 to line 4.
@media (min-width: 880px) {
    .c-newspaper {
        grid-template-columns: 1fr 2fr 1fr;
    }
    
    .c-newspaper__col:first-child {
        grid-column: 2/3;
    }
  
    .c-newspaper__col:last-child {
        grid-column: 3/4;
    }
}

A visual demo

Now that we’ve a working grid, we will begin fascinated by the interior parts and how you can construct them.

Card element

That is the core focus of this text, the cardboard element. I compiled a visible of all of the variations we’ve:

All of these can stay inside the featured part however with a distinct design variation for every card.

Let’s take the default card for instance:

In vox.com HTML, the cardboard has the next CSS courses:

<div class="c-entry-box--compact c-entry-box--compact--article c-entry-box--compact--hero c-entry-box--compact--2"></div>

That could be a lengthy listing of CSS courses, and the category identify itself is prolonged, too.

A take a look at just a few particulars on Vox structure

Card thumbnail

The cardboard element is inbuilt a approach that makes use of quite a lot of variation courses. For instance, right here is how the thumbnail is hidden within the plain card:

.c-entry-box--compact--7 .c-entry-box--compact__image-wrapper {
    show: none;
}

A customized variation class is used for each single card within the featured part. In whole, the CSS seems like this:

That’s an excessive amount of, I feel.

Card title measurement

The title measurement for the default card is 20px and 16px for the plain card (and not using a thumbnail).

Right here is how that’s dealt with on vox.com:

@media (min-width: 880px)
    .c-newspaper .c-entry-box--compact__title {
        font-size: .9em;
    }
}

The .c-newspaper is the principle component that incorporates all of the playing cards, so utilizing it like that to tag the title component doesn’t look proper to me. What if that must be utilized in one other container that doesn’t have the category .c-newsppaper?

Separator

There’s a line separate between playing cards. It’s being dealt with within the CSS like this:

.c-newspaper .c-entry-box--compact {
    border-bottom: 1px strong #d1d1d1;
}

Two issues that don’t look good to me right here:

  • Utilizing .c-newspaper component to pick the cardboard.
  • Including the separator on to the cardboard itself. This can be a conditional fashion that isn’t associated to the cardboard.

Rethinking the cardboard with fashionable CSS

The primary motivation for this text is the cardboard element. Once I began fascinated by it, I received the thought to make use of some or all of those options:

  • CSS grid
  • aspect-ratio
  • textual content wrap balancing
  • CSS :has
  • Fluid sizing and spacing
  • Measurement container queries
  • Type container queries

I already explored utilizing CSS grid for the principle structure. Here’s what the HTML markup seems like:

<div class="c-newspaper">
    <div class="c-newspaper__col">
        <div class="c-newspaper__item">
            <article class="c-card">
                <!-- Card element -->
            </article>
        </div>
        <div class="c-newspaper__item"></div>
        <div class="c-newspaper__item"></div>
    </div>
    <!-- Different columns -->
</div>

The cardboard element lives inside the .c-newspaper__item, which acts as the cardboard container.

Usually talking, I wish to wrap the element in an summary container. That is helpful for:

  • Including borders
  • Controlling the spacing
  • Works nicely for measurement container queries

Card meta font household

When the cardboard element is inside the featured part, the font household of the creator’s identify is completely different. To try this, we will test if the next container question works, and if sure, the font will probably be utilized.

@container principal (min-width: 1px) {
    .c-card__meta {
        font-family: "Playfair Show", serif;
    }
}

Default card fashion

We have to set a default card fashion that we will fashion. On this case, each the horizontal and stacked types are used equally, however I’ll assume that the stacked card is used extra, only for the sake of the article.

<article class="c-card">
    <div class="c-card__thumb"></div>
    <div class="c-card__content">
        <h3 class="c-card__title"></h3>
        <p class="c-card__tease"></p>
        <p class="c-card__meta"></p>
    </div>
</article>

Cool! Let’s from there for the remainder of the variations.

Horizontal fashion

The cardboard will flip to the horizontal fashion when its container is bigger than 300px and the CSS variable --horizontal: true has been set on the container.

<div class="c-newspaper__item" fashion="--horizontal: true;">
    <article class="c-card"></article>
</div>
.c-newspaper__item {
    container-type: inline-size;
    container-name: card;
}

@container card (min-width: 300px) and fashion(--horizontal: true) {
    .c-card {
        show: flex;
        hole: 1rem;
    }
}

Discover that I mixed a measurement and a mode container question. The dimensions question works based mostly on the container width. Whereas the fashion question works by checking if the CSS variable is there.

We even have the identical variation however with the cardboard thumbnail positioned being flipped. We are able to try this by way of the order property.

To question that, we have to add the variable --flipped: true.

<div class="c-newspaper__item"
    fashion="--horizontal: true; 
           --flipped: true">
</div>

At first, I attempted the next CSS however it didn’t work as anticipated. It’s not doable to merge two container queries for various containers. In my case, the containers are principal and card.

/* That did not work */
@container principal (min-width: 550px) and card fashion(--flipped: true) { }

After studying the spec, I observed the next:

Whereas it isn’t doable to question a number of containers in a single container question, that may be achieved by nesting a number of queries:

I nested the fashion question inside one other container question. In plain phrases, that’s like saying:

When the container principal width is the same as or bigger than 550px and the CSS variable –flipped is about on the playing cards container, apply the next CSS.

.wrapper {
    max-width: 1120px;
    margin: 1rem auto;
    padding-inline: 1rem;
    container-name: principal;
    container-type: inline-size;
}

@container principal (min-width: 550px) {
    @container card fashion(--flipped: true) {
        .c-card__thumb {
            order: 2;
        }
    }
}

To study extra about container queries, listed below are just a few write-ups on the subject:

Card thumbnail side ratio

The present approach of implementing ting the cardboard thumbnail doesn’t account for when there may be a picture with a distinct side ratio. We are able to use the CSS aspect-ratio property to drive the cardboard thumb to have the identical side ratio.

Let’s assume that I added a big picture that has a distinct side ratio. We’ll find yourself with one thing like this:

To keep away from that, we will outline a side ratio:

.c-card__thumb img {
    aspect-ratio: 5/3;
    object-fit: cowl;
}

If you’re to study extra about side ratio, I wrote an article about that.

Card horizontal fashion

On vox.com, the horizontal card fashion was inbuilt a approach that feels a bit pointless.

See Also

/* CSS from vox.com */
.c-entry-box--compact__image-wrapper {
    width: 30%;
}

.c-entry-box--compact__body {
    flex-grow: 1;
    width: 70%;
}

Why is that? I assume that’s to keep away from having such a UI habits:

Discover that I discussed “UI habits”, not a bug. The above is a default habits for flexbox. We have to drive the picture to have a hard and fast and constant measurement.

.c-entry-box--compact__image-wrapper {
    flex: 0 0 30%;
}

.c-entry-box--compact__body {
    flex-grow: 1;
}

We are able to repair that by merely utilizing the flex property. No want to make use of the width.

The featured card is displayed horizontally when the container width is small and can change to the stacked types on bigger sizes. On this case, the thumbnail turns into bigger and takes 50% of the width.

Here’s a comparability between a default horizontal fashion and the featured one.

When the container width turns into bigger, the cardboard fashion will turn into stacked.

To implement that, I used the --featured variable on the cardboard’s container.

<div class="c-newspaper__item"
    fashion="--featured: true;">
</div>

Firstly, I added the horizontal fashion as default.

  • Added flex to activate the horizontal design.
  • The cardboard thumb takes 50% of the out there width.
  • Modified the font household to a serif font and a bigger measurement, as per the design.
@container fashion(--featured: true) {
    .c-card {
        show: flex;
        hole: 1rem;
    }

    .c-card__thumb {
        flex: 0 0 50%;
    }
  
    .c-card__tease {
        font-family: "Playfair Show", serif;
        font-size: 19px;
    }
}

When the container measurement will get bigger, the browser will apply the stacked styling to the cardboard.

@container principal (min-width: 550px) {
    @container card fashion(--featured: true) {
        .c-card {
            flex-direction: column;
            hole: 0;
        }

        .c-card__title {
            font-size: calc(1rem + 2.5cqw);
        }

        .c-card__content {
            text-align: heart;
        }
        
        .c-card__thumb {
            flex: preliminary;
        }
    }
}

Plain card

On this variation, the font measurement will get smaller. That occurs when the picture is hidden. At first, I thought of utilizing CSS :has to test if the cardboard thumb is displayed or not.

In vox.com, the cardboard thumb is hidden by way of CSS, so it’s not doable to make use of :has as it is going to be legitimate even when the thumb is hidden.

<article class="c-card">
    <div class="c-card__thumb"></div>
    <div class="c-card__content"></div>
</article>
.c-card__thumb {
    show: none;
}

/* This may all the time work. */
.c-card:has(.c-card__thumb) .c-card__title {
    font-size: 19px;
}

If the picture will be conditionally added by way of Javascript, then we will use :has. In any other case, I’ll default to a mode question.

@container principal (min-width: 550px) {
    @container card fashion(--compact: 2) {
        .c-card__title {
            font-size: 19px;
        }
    }
}

Spacing and separators

The present approach in vox.com to deal with the spacing is by including padding on to the cardboard. I don’t favor that. The cardboard types shouldn’t depend upon the place it lives. The spacing must be added to the cardboard’s wrapper as a substitute.

To make issues simpler, I added a CSS variable --gap to every column.

.c-newspaper__col {
  --gap: 20px;
  show: flex;
  flex-direction: column;
}

I added a margin-block to every card wrapper.

  • On small viewports, there are not any separators.
  • When the scale is medium, there are separates for the primary two columns, and one border for the final one.

The CSS property margin-block is a logical property which means each margin-top and margin-bottom.

@media (min-width: 550px) {
  .c-newspaper__item:not(:last-child):after {
    content material: "";
    show: block;
    top: 1px;
    background-color: lightgrey;
    margin-block: var(--gap);
  }
  
  .c-newspaper__col:last-child {
    border-top: 1px strong lightgrey;
    padding-top: var(--gap);
  }
}

@media (min-width: 880px) {
  .c-newspaper__col:last-child {
    padding-top: 0;
    border-top: 0;
  }
  
  /* Add separators to the final column */
  .c-newspaper__col:last-child .c-newspaper__item:not(:last-child):after {
    content material: "";
    show: block;
    top: 1px;
    background-color: lightgrey;
    margin-block: var(--gap);
  }
}

You is likely to be pondering, why not use hole? The reason being that I received’t use fashionable CSS for the sake of utilizing it. It’s not helpful right here as a result of:

  • it solely works for one a part of the spacing, and I’ve to make use of margin-top with it.
  • I want there’s a native CSS approach so as to add borders, identical to the CSS property column-rule in CSS columns.

Container models

One factor that I like about container queries is the flexibility to make use of container models. They’re like viewport models however for a particular container. Isn’t that highly effective?

@container principal (min-width: 550px) {
    @container card fashion(--featured: true) {
        .c-card__title {
            font-size: clamp(1rem, 6cqw, 2rem);
        }
    }
}

Be taught extra about container query units.

Textual content balancing

Not too long ago, I wrote concerning the new CSS characteristic text-wrap: stability, which continues to be in Chrome Canary solely on the time of writing this text.

Within the structure that I’m constructing, we will leverage that for all of the textual content content material. It could make the structure look extra organized.

Be taught extra about text wrap balancing.

Ultimate demo

You’ll be able to play here with the ultimate demo. I like to recommend checking that on Chrome Canary.

Disclaimer: the design isn’t an identical to Vox, this demo focuses extra on the structure and parts implementation.

Outro

One of many issues that drive me to study and discover CSS is the curiosity to see how people construct issues. I get pleasure from that course of and study lots whereas doing so. I hope you discovered the article useful.

Do you may have a query or suggestions? Please be at liberty to ping me on Twitter @shadeed9.



Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top