Friday, May 3, 2024
HomeCSSRebuilding a featured information part with trendy CSS: Vox information

Rebuilding a featured information part with trendy CSS: Vox information


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

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

Article collection

Desk of contents

Analyzing the part

Within the largest viewport, now we have 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 now we have 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 are able to have an thought about what’s altering on every viewport dimension.

Modifications from the massive to medium

  • Featured part: virtually the identical, however with a special font dimension that’s altering primarily based on the viewport width.
  • Blue part: the font dimension of every card title obtained smaller.
  • Pink part:
    • The primary article’s thumb is hidden.
    • Format is modified from one column to a few columns.
    • Including a separator on the prime of the part.

Modifications from medium to small

  • All articles will change to the horizontal model with the thumbnail proven for every one.
  • The featured article will develop into horizontal, however with a bigger thumbnail to distinguish it from the remainder of the articles.

With that in thoughts, now we have a primary define of how the structure is behaving on totally 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 objective as this feels extra like a CSS grid use case. I consider the Vox group 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 liable for the next:

  • Setting the width of the column. Utilizing width property for that works high quality, however we are able to additionally use the flex property.
  • Including padding on the left and proper sides is an previous solution to introduce a spot between columns. Now now we have the hole property!

We will 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 take care of the sizing and spacing. Additionally, I’m an advocate of utilizing grid for layouts and flexbox for parts.

Take into account the next HTML markup:

<div class="c-newspaper">
  
  <div class="c-newspaper__col">1</div>

  
  <div class="c-newspaper__col">2</div>
  <div class="c-newspaper__col">3</div>
</div>

I added numbers for illustrating how every structure column can be reordered on totally different viewport sizes.

CSS grid sounds excellent 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 good thing about the hole property for spacing.
  • When the viewport width is 550px or bigger, the grid can have 3 columns. The identical occurs on the bigger viewport 880px, however the second column is double the dimensions of its sibling columns.

The vox.com kinds for the columns are constructed with the order property to reposition the columns on totally 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 are able to reorder the structure by positioning a component on any grid strains we wish.

Let’s discover find out how to place the structure columns with CSS grid.

The medium viewport dimension

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

  • 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 massive viewport dimension

And for the massive dimension, do not forget that the second column is now 2fr, so it should double the dimensions of the facet column.

  • The primary column is positioned from line 2 to line 3.
  • The second line stays throughout the identical 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 visible demo

Now that now we have a working grid, we are able to begin desirous about the inside parts and find out how to construct them.

Card part

That is the core focus of this text, the cardboard part. I compiled a visible of all of the variations now we have:

All of these can dwell throughout the featured part however with a special 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 checklist of CSS courses, and the category identify itself is prolonged, too.

A take a look at a number of particulars on Vox structure

Card thumbnail

The cardboard part is inbuilt a approach that makes use of plenty 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 complete, the CSS appears to be like like this:

That’s an excessive amount of, I believe.

Card title dimension

The title dimension for the default card is 20px and 16px for the plain card (with no 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 accommodates 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 stable #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. It is a conditional model that isn’t associated to the cardboard.

Rethinking the cardboard with trendy CSS

The principle motivation for this text is the cardboard part. Once I began desirous about it, I obtained 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
  • Fashion container queries

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

<div class="c-newspaper">
  <div class="c-newspaper__col">
    <div class="c-newspaper__item">
      <article class="c-card">
        
      </article>
    </div>
    <div class="c-newspaper__item"></div>
    <div class="c-newspaper__item"></div>
  </div>
  
</div>

The cardboard part lives throughout the .c-newspaper__item, which acts as the cardboard container.

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

  • Including borders
  • Controlling the spacing
  • Works properly for dimension container queries

Card meta font household

When the cardboard part is throughout the featured part, the font household of the writer’s identify is totally different. To try this, we are able to test if the next container question works, and if sure, the font can be utilized.

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

Default card model

We have to set a default card model that we are able to model. On this case, each the horizontal and stacked kinds 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 model

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

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

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

Discover that I mixed a dimension and a method container question. The dimensions question works primarily based on the container width. Whereas the model 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 will try this through the order property.

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

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

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


@container primary (min-width: 550px) and card model(--flipped: true) {
}

After studying the spec, I seen the next:

Whereas it’s not 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 model question inside one other container question. In plain phrases, that’s like saying:

When the container primary 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: primary;
  container-type: inline-size;
}

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

To study extra about container queries, listed here are a number of 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 special side ratio. We will use the CSS aspect-ratio property to power the cardboard thumb to have the identical side ratio.

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

To keep away from that, we are able to outline a facet ratio:

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

In case you are to study extra about side ratio, I wrote an article about that.

Card horizontal model

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


.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 power the picture to have a set and constant dimension.

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

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

We will 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 kinds 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 model and the featured one.

When the container width turns into bigger, the cardboard model will develop into stacked.

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

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

Firstly, I added the horizontal model as default.

  • Added flex to activate the horizontal design.
  • The cardboard thumb takes 50% of the accessible width.
  • Modified the font household to a serif font and a bigger dimension, as per the design.
@container model(--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 dimension will get bigger, the browser will apply the stacked styling to the cardboard.

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

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

    .c-card__content {
      text-align: middle;
    }

    .c-card__thumb {
      flex: preliminary;
    }
  }
}

Plain card

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

In vox.com, the cardboard thumb is hidden through CSS, so it’s not doable to make use of :has as will probably 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;
}


.c-card:has(.c-card__thumb) .c-card__title {
  font-size: 19px;
}

If the picture will be conditionally added through Javascript, then we are able to use :has. In any other case, I’ll default to a method question.

@container primary (min-width: 550px) {
  @container card model(--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 desire that. The cardboard kinds shouldn’t rely on 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 dimensions 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 stable lightgrey;
    padding-top: var(--gap);
  }
}

@media (min-width: 880px) {
  .c-newspaper__col:last-child {
    padding-top: 0;
    border-top: 0;
  }

  
  .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 could be considering, why not use hole? The reason being that I received’t use trendy 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, similar 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 selected container. Isn’t that highly effective?

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

Be taught extra about container question models.

Textual content balancing

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

Within the structure that I’m constructing, we are able to leverage that for all of the textual content content material. It might probably make the structure look extra organized.

Be taught extra about textual content wrap balancing.

Remaining demo

You possibly can play right 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 power me to study and discover CSS is the curiosity to see how other people construct issues. I get pleasure from that course of and study so much whereas doing so. I hope you discovered the article useful.

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



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments