Tag: Layouts

10 modern layouts in 1 line of CSS

, ,

Create Diagonal Layouts Like it’s 2020

Nils Binder covers the ways:

1. Use an SVG in the form of a triangle. This technique is nicely described by Erik Kennedy on CSS-Tricks.

2. Hide part of your section using clip-path. Read Diagonal Containers in CSS by Sebastiano Guerriero or Sloped edges with consistent angle in CSS by Kilian Valkhof.

3. Using CSS Transforms

I would normally be a #2 kinda guy — slice off the top and bottom a bit, make sure there is ample padding, and call it a day. But Nils almost has me convinced this fancy math is better.

Here’s a kinda dumb clip-path way:

And Nils incredibly fancy playground:

Direct Link to ArticlePermalink

The post Create Diagonal Layouts Like it’s 2020 appeared first on CSS-Tricks.


, , , , ,

Four Layouts for the Price of One

Pretty notable when a tweet about a flexbox layouts gets 8K+ likes on Twitter!

That’s “native” CSS nesting in use there as well, assuming we get that at some point and the syntax holds.

There was some feedback that the code is inscrutable. I don’t really think so, to me it says:

  • All these inputs are allowed both to shrink and grow
  • There is even spacing around all of it
  • The email input should be three times bigger than the others
  • If it needs to wrap, fine, wrap.

A great use case for flexbox, which is the right layout mechanism when you aren’t trying to be super precise about the size of everything.

There is a blog post (no byline 🤷‍♂️) with a more longwinded explanation.

This reminds me a lot of Tim Van Damme’s Adaptive Photo Layout where photos lay themselves out with flexbox. They don’t entirely keep their aspect ratios, but they mostly do, thanks to literally the flexibility of flexbox.

Here’s a fun fork of the original.

It’s like a zillion layouts for the price of one, and just a few lines of code to boot.

The post Four Layouts for the Price of One appeared first on CSS-Tricks.


, ,

Building Multi-Directional Layouts

There are some new features in CSS that can assist us with building layouts for different directions and languages with ease. This article is about CSS logical properties and values (e.g. margin-inline-start).  These are a W3C working draft that still going under heavy editing, but have shipped in many browsers. I want to talk about this because I’ve been using these properties for a little while and have seen a significant boost to my workflow after switching to them.

I’ll talk about the specifications and how can you use it today in your work. I live in Egypt where we use Arabic as a primary language. Arabic is written from right to left, which means Arabic websites look like a mirror image of an English version. Most of the websites we create are bilingual, which means we provide a stylesheet specific for each direction. We do that by flipping values and properties of almost everything! I will not talk in details about this part but you can talk a quick look about a past article I wrote on the topic. 

It starts with declaring the dir attribute on the HTML tag. 

 <html dir="rtl">

This attribute accepts one of two values: ltr (which is the default value if none is specified) and rtl. According to its value, the browser starts to paint the elements following a specific algorithm. Text will be written with respect to the direction and punctuations will be placed in their correct location. Some elements, like tables, will have their direction switched (for example, a <td> starting from the right in rtl). Thankfully, some new specifications, like CSS Grid, and flexbox follow a similar approach to the table. That means we don’t have to change the order of anything because the browser will take care of it!

HTML5 introduced a new auto value for the dir attribute. It will check for the first character within the element and, if it belongs to a language that is written from left-to-right (like Latin characters), the element will have an ltr direction and vice versa. The W3C urges authors to avoid relying on this value to determine text direction and use a server-side solution instead. 

An interesting use case for the auto value is when you’re unsure about the direction of the content, such user-generated content, like a comment thread. I see a lot of people contributing to discussions in Arabic websites in English. The support for auto is pretty good except, for Internet Explorer and Edge.

Introducing the :dir() pseudo-class

The :dir() pseudo-class is a new selector modifier that selects an element by evaluating its direction value. It works like this:

/* Select all paragraphs that have their computed direction value set to rtl */ p:dir(rtl) {   font-size: 16px; /* Sometimes Arabic glyphs need a size boost to feel right. */ } 
 /* Select all paragraphs that have their computed direction value set to ltr */ p:dir(ltr) {   font-size: 14px; }

The beauty of this selector is that it’s the first one to select elements based on a computed value. Whether the direction of the element was inherited from the HTML dir attribute or set using CSS like html:lang("ar") { direction: rtl; }, the selector will match the element. Even better, if you have the direction of the element set to auto, it will still correctly the element based on its content!

<style>   p {     direction: auto;   }   p:dir(ltr) {     background: green;   }   p:dir(rtl) {     background: red;   } </style> 
 <!-- The following paragraph will have a green background --> <p>This is a paragraph that starts with a latin character</p> <!-- The following paragraph will have a red background --> <p>هذا النص يستخدم حروف عربية</p>

Sadly, the support for :dir() isn’t great and limited only to Firefox.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.


Chrome Opera Firefox IE Edge Safari
No No 17* No No No

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
No No No No No 68

Even if the browser support was great, the selector only allows you to target elements and manually apply certain styles to them. That means that we still should flip the values for everything (like margins, paddings, floats, positions, etc.) which doesn’t really enhance our workflow or reduce the effort to produce multi-directional layouts.

Introducing CSS logical properties and values

As defined by the W3C, logical properties and values provide us with the ability to control layout through logical, rather than physical, direction and dimension mappings. Let’s skip the technical jargon and jump directly to the details. These provide us with new properties and values that will evaluate differently according to certain conditions.

Logical values

Let’s say we have a paragraph that we want to align in a direction that’s opposite to the natural direction of the language. Let’s say this is in English that follows the ltr direction. We would do something like this:

<article>   <p class="opposite">     Lorem ipsum dolor sit amis ..   </p> </article>

And the CSS file would be like this:

.opposite {   text-align: right; }

To provide the opposite for the rtl version, we would override the selector by targeting the <html> tag with the dir attribute, or simply provide a different file for the rtl version, like this:

html[dir="rtl"] .opposite {   text-align : left; }

Logical properties and values were created to solve this problem. Why don’t we use values that evaluates to the correct context instead of using left and right? In an ltr element, the value left means the beginning or the start of the element while on the rtl element, the value right means the start! It’s simple, right?

So instead of what we wrote before, we can use:

.opposite {   text-align: end; }

And that’s it! If the element’s computed direction is ltr, the text would be aligned right; and the computed direction would be opposite for the rtl elements. So, instead of using left and right values for text-align, we can simply replace it with start and end. This is a lot easier and more convenient than our previous options.

Logical properties

What we just looked at were logical values, so let’s turn now to logical properties. Logical properties are new properties that have the same idea; they evaluate differently according to the direction of the element. Take a look at margin as an example. Previously, we wanted to add some space toward the start of the paragraph. We can do so in the ltr document by using:

article img {   margin-left: 15px; }

Now, in the case of the rtl version, we will need to add the margin to the opposite direction in addition to resetting the left value:

html[dir="rtl"] article img {   margin-left: 0;   margin-right: 15px; }

We can do better with logical properties. Consider the following:

article img {   margin-inline-start: 15px; }

The -inline-start part evaluates to the beginning of the horizontal axis of the image. In the case of ltr, that means left, and in the case of rtl, that means right.

The start and end are probably obvious by now, but what is with the word inline and why do we need it? To understand it, we need to talk about something called CSS writing modes. Jen Simmons wrote an excellent article on that topic. I won’t regurgitate everything explained there, but the bottom line is that we can use writing modes to define the writing direction. Some languages, like the Chinese, Korean, and Japanese, can be written vertically from top to bottom. CSS writing modes allow us to control that flow. Take a look at the following paragraph:

You can clearly identify the top, bottom, left and right edges of the block. What will happen if we change the direction of the paragraph using CSS writing modes to flow vertically?

When we talk about the “top” of this rotated paragraph, do we mean the where the content begins or what was the right edge when it wasn’t rotated? Identifying the four directions becomes confusing. Let’s look at them from a different perspective. In “normal” writing conditions, the vertical axis will have the suffix -block and the horizontal axis will have the suffix -inline, both followed by start or end:

And if we rotate it, it should be like this:

Since we are talking about normal horizontal layout, we will be using -inline-start and -inline-end, but it is good to know about the other properties as well. We can also write logical shorthand values by using the logical keyword. Consider the following:

article img {   margin: logical 10px 20px 30px 40px; }

The computed value of the image’s margin will be the following:

article img {   margin-block-start: 10px;   margin-inline-start: 20px;   margin-block-end: 30px;   margin-inline-end: 40px; }

The logical keyword is an experimental feature at this point in time, which means it may change or it may be replaced by the time the spec becomes official. There’s an open discussion on the topic that you can follow in the meantime.

Logical properties also allow us to apply values to a certain axis, meaning we have margin-inline and margin-block for the horizontal and vertical axises, respectively.

Property Logical Property
margin-top margin-block-start
margin-left margin-inline-start
margin-right margin-inline-end
margin-bottom margin-block-end

Just like with the logical margin properties, we also have logical padding properties which follow the same rules as the margin.

Property Logical Property
padding-top padding-block-start
padding-left padding-inline-start
padding-right padding-inline-end
padding-bottom padding-block-end

Logical positioning properties

In the previous examples we were able to modify the meaning of the property by appending suffixes, but what about the positions? The properties names changed completely from what we know now as top, right, bottom, and left.

.element {   position: absolute;   inset-block-start: 0;  /* evaluates to top */   inset-block-end: 0;    /* evaluates to bottom */   inset-inline-start: 0; /* evaluates to left in ltr and right in rtl */   inset-inline-end: 0;   /* evaluates to right in ltr and left in rtl */ }

Learning new properties and values can be hard but, hey, we get a shorthand property called inset to make it a little easier:

/* Shorthand FTW! */ .element {   position: absolute;   inset: logical 10px 20px 30px 40px; } 
 /* It evaluates to this */ .element {   position: absolute;   inset-block-start: 10px;   inset-inline-start: 20px;   inset-block-end: 30px;   inset-inline-end: 40px; }

inset supports both inset-block and inset-inline just like margin and padding.

Property Logical Property
top inset-block-start
left inset-inline-start
right inset-inline-end
bottom inset-block-end

Logical border properties

Border properties can also become logical by appending the -inline-start and -block-start.

Property Logical Property
border-top{-size|style|color} border-block-start{-size|style|color}
border-left{-size|style|color} border-inline-start{-size|style|color}
border-right{-size|style|color} border-inline-end{-size|style|color}
border-bottom{-size|style|color} border-block-end{-size|style|color}

In her deep dive on logical properties and values, Rachel Andrew includes an excellent demo that demonstrates logical border properties and how they respond to different writing modes.

How can we start using all this today?

We can start using all the magic of logical properties and value today, thanks to the power of PostCSS! Jonathan Neal wrote this lovely PostCSS plugin that enables us to write logically and compile the code to something today’s browsers will understand. The plugin works in three stages:

  • It translates the new syntax to existing standards that unsupported browsers will recognize, using the :dir pseudo-class to create output to ltr and rtl.
  • It uses another one of Neal’s plugins to translate :dir to an attribute selector, like this:
 .element:dir(ltr) {    ...  }  [dir="ltr"] .element {    ...  }
  • It uses the postcss-nested plugin to transform nested selectors to one-line selectors, the same way other CSS preprocessors do.

PostCSS works with any workflow. You can try it with Grunt, Gulp, and webpack.

I will close by saying I have seen a lot of benefits since making the shift to logical properties and values. Sure, building multi-directional layouts takes time. There’s the learning curve, the addition of more properties to write, and of course, testing. Our previous methods for creating multi-directional layouts were either taking care of both directions in development or working on one direction at a time — neither of which is all that suitable for big projects. With logical properties and values you write your code once and it works for both directions without any consideration.


The post Building Multi-Directional Layouts appeared first on CSS-Tricks.


, ,

Bringing CSS Grid to WordPress Layouts

December 6th, 2018 was a special date for WordPress: it marked the release of version 5.0 of the software that, to this day, powers more than one-third of the web. In the past, people working on the platform pointed out that there has never been any special meaning to version numbers used in WordPress releases; as such, WordPress 5.0 was simply the follower to WordPress 4.9. Yet, 5.0 brought possibly the biggest innovation since Custom Post Types were introduced in version 3.0 – that’s almost a decade, folks.

The Block Editor — codename “Gutenberg” — is now the new default writing tool in WordPress. Before its adoption in Core, our beloved CMS has relied on what we now call the Classic Editor. And, by the way, the Classic Editor isn’t really gone: you can bring it back by installing a plugin that restores the default editing experience you’ve known all these years.

So, why was the Classic Editor replaced? Essentially because it embodied an old concept of writing, a concept that was conceived when the only need of a text editor was to visually compose HTML code.

Not to create layouts. Not to embed dynamic content form heterogeneous sources. Not to offer a representation of what your post or page would look like when you pressed that “Publish” button, and go live with your piece of content.

In short, the Classic Editor delivered a very basic writing experience and, frankly, it always fell short at creating anything more than flowing text.

The Block Editor is based on the idea of content “blocks” in the sense that everything we can add to a page — a text paragraph, an image, an embed — is technically a block, that is, an atomic entity that’s defined by a certain series of properties. The combination of these properties determines the state of that particular block. Combine several blocks one after the other, and you’ll get the content of your page.

In this transition from unorganized text to rigorous content structure lies the biggest change introduced by the Block Editor.

Layouts pre-Block Editor

Before all of this bursted into existence, people who wanted to create a layout within WordPress had to choose between either of these options:

  1. Create a custom template from scratch, getting their hands dirty with code – a noble intent, yet not so appealing to the masses.
  2. Use a tool, better if a visual one, that helped them composing a page structure without having much code knowledge.

That’s how page builders were born: page builders are plugins that provide a visual way to compose a layout, ideally without touching a single line of code, and they were created out of necessity to fill a gap between visual mockups and the actual, finished website. Elementor and Beaver Builder are two popular builders that come to mind.

Page builders have always suffered from a bad reputation, for a variety of reasons:

  1. They tend to be slow and bulky.
  2. Some offer poor editing experiences.
  3. They end up locking users into a framework or ecosystem that’s tough to replace.

The first point is as obvious as it is unavoidable: if you’re a page builder author (and, hopefully, aspire to sell copies of your product), you have to make it as appealing as possible; physiologically, builders started to slowly become big code soups with everything in them, at the detriment of performance.

The second point may be subjective, at least to to some extent. The third point, however, is a fact. Sure, one could be perfectly fine using the same tool for every project, perfecting knowledge of the instrument as time goes by, but the more you stick to it, the harder it gets to potentially stop using it one day.

The Block Editor aims to surpass this deadlock: from the user’s point of view, it aims at offering a better, richer writing experience, while, from the developer’s perspective, providing a unified, shared API from which to build upon.

A brief history of CSS layouts

If you’re old enough, you’ll probably know the story already. If not, it might be fun for you to hear what life was like for a front-end developer back in the day.

The first version of the CSS specification dates back to 1996, and it allowed an embedded stylesheet to add font styling, pick colors for elements, change the alignments and spacing of objects in the page. The problem was that, in those days, the concept of semantic HTML wasn’t exactly widespread. In other words, there was no clear separation between content and form. The markup we’d write and the appearance we want were completely intertwined in the same document.

This led to HTML elements to be used more for presentation purposes, than conveying meaning to their presence in the page. For example, on the layout side of things, this also led to to table elements being used to create layouts instead of actual tabular data. To achieve even more complex layouts, tables began being nested into other tables, making the page become a nightmare from the semantic point of view, its size grow and grow, and resulting very hard to maintain over time. If you’ve ever coded an HTML email, then you have a good idea of what life was like. And, really, this still sort of happens in websites today, even if it’s for smaller elements rather than complete page layouts.

Then the Web Standards movement came along with the goal to raise awareness among developers that we could be doing things differently and better; that style and content should be separated, that we need to use HTML elements for their meaning, and reinforcing the concept that a lighter page (in terms of code weight) is a fundamentally better option than an unmanageable ocean of nested tables.

We then began (over)using div elements, and juxtaposed them using the float property. The presentation focus was shifted from the markup to the stylesheet. Floats became the most reliable layout tool available for years, yet they can be a bit problematic to handle, since they have to be cleared in order for the page to return to its standard flow. Also, in this age, page markups were still too redundant, even though using divs instead of tables helped make our content more accessible.

The turnaround moment came in 2012, with the publication of the Flexbox specification. Flexbox allowed developers to solve a whole series of long standing little layout problems, complete with an elegant syntax that requires a lot less markup to be implemented. Suddenly (well, not that suddenly, we still have to care about browser support, right?), reliably centering things on both axises wasn’t an issue anymore. It was refreshing. Finally, tweaking a layout could be reduced to altering just one property in our stylesheet.

As important as Flexbox is to this day, it is not the end of the story.

It’s 2019! Let’s use CSS Grid.

If you’ve come this far reading this piece, we think it’s safe to assume that two things are for sure:

  1. That we clearly aren’t in this industry to live peaceful, quiet professional lives.
  2. The things we use are going to change.

In 2017, the CSS Grid Layout Module specification was officially published, but, as it always happens with CSS specs, its draft and interim implementations had already been around for some time.

CSS Grid is a bold leap into what CSS can and should do. What if we stopped micromanaging our pages styles, and started thinking more holistically? What if we had a system to reliably position elements on the screen that doesn’t depend at all on the markup being used, nor the order of elements, and that is, at the same time, programmatically applicable on smaller screens?

No, this isn’t just a thought. This is more of a dream; one of those good ones you don’t want to wake up from. Except that, in 2019, this has become a reality.

The main difference between Grid and Flexbox is more nuanced, of course, but basically comes down to Grid operating in two dimensions, while Flexbox is limited to one. Knowing what elements are going to be placed within the limits of a container, we can choose exactly where those elements are going to end up, entirely from directives written in the stylesheet.

Do we want to tweak the layout down the road? Fine, that modification won’t affect the markup.

The basic idea behind Grid is that elements are laid out in, well, a grid. By definition, a grid is composed by a certain amount of columns and rows, and the boundaries between columns and rows form a series of cells that can be filled with content.

The savings of this approach in terms of quantity of code being used to achieve the desired result are extraordinary: we just need to identify a container element, apply the display: grid rule to it, and then pick elements within that container and tell CSS what column/row they begin/end in.

.my-container {   display: grid;   grid-template-columns: repeat( 3, 1fr );   grid-template-rows: repeat( 2, 1fr ); }  .element-1 {   grid-column-start: 2;   grid-column-end: 4;   grid-row-start: 1;   grid-row-end: 3; }

The above example creates a 3×2 grid associated to the .my-container element; .element-1 is a 2×2 block that is inscribed in the grid, with its upper left vortex being positioned in the second column of the first row of the grid.

Sounds pretty neat, right?

The even neater thing about CSS Grid is the fact that you can create template areas, give those areas meaningful names (e.g. “header” or “main”), and then use those identifiers to programmatically position elements in those areas.

.item-a {   grid-area: header; } .item-b {   grid-area: main; } .item-c {   grid-area: sidebar; } .item-d {   grid-area: footer; }  .container {   display: grid;   grid-template-columns: 50px 50px 50px 50px;   grid-template-rows: auto;   grid-template-areas:      "header header header header"     "main main . sidebar"     "footer footer footer footer"; }

For those who have begun working in this business in the tables era, the code above is nothing short of science fiction.

More good news, anyway: support for CSS Grid is pretty great, today.

Using CSS Grid in WordPress

So, this is great, and knowing that we can do so many more things today than we could compared to a few years ago probably makes you want to give Grid a try, at last.

If you are working on a WordPress project, you’re back facing the two options mentioned above: do we start from scratch and manually coding a template, or is there something that can give us a little help? Luckily, there is a plugin that might interest you, one that we have created with a dual goal in mind:

  1. Create a bridge between the Block Editor and CSS Grid.
  2. Create a plugin that could perhaps make people move past the initial skepticism of adopting the Block Editor.

It’s called Grids, and it’s a free download on the WordPress plugins repository.

Grids only takes care of the layout structure. It puts a 12×6 grid at your disposal (called Section), over which you can drag and draw the elements (Areas) that are going to be contained in that Section.

The system allows you to manually specify dimensions, backgrounds, responsive behavior, all using visual controls in the Block Editor, but by design, it doesn’t provide any content block. Sure, one could see this approach as a weak point, but we think it’s actually Grids’ biggest strength because it enables the plugin to integrate with the myriad content blocks that other developers all around the world are creating. More so, in a way Grids helps bringing those blocks, and WordPress as a platform, in touch with CSS Grid itself.

Yet, even if the plugin doesn’t strictly produce content, it’s inevitable to put it in the same phrase with successful page builders, in fact comparing its functionality to that offered by those. If you care about concepts like separation of form and content, page weight, ease of maintenance, Grids offers a cleaner solution to the problem of creating visually appealing layouts in WordPress.

The generated markup is minimal. In its most basic form, a Section (that is, the element with the display: grid property) is only composed by its own element — of course, an internal wrapper (that couldn’t be avoided and that’s used for spacing purposes), and then one element per Area belonging to the Section. This is a huge step forward in terms of avoiding using unnecessary markup.

For those of you who haven’t been afraid of getting your hands dirty with the development of blocks for the Block Editor, the rendering of the block is done server-side, which allows for custom classes to be added to Section and Area elements using filters.

This choice also directly determines what happens in the eventuality that you disable Grids in your install.
​​If you don’t re-save your page again, what’s left of Grids on the front end is actually exclusively the content you put inside the content Areas. Not any extra markup elements, not any weird-looking shortcode.
​​On the back-end side of things, the Block Editor has a system in place that warns you if you’re editing a page that is supposed to use a particular block type, but that block type isn’t currently available: in that case, you could easily turn Grids back on temporarily, move your content in another place, and then get rid of the Section altogether.

CSS generated to create the grid is also dynamically added to the page, as an inline style in the <head> portion of the document. We haven’t been exactly fans of styles written in the page directly, because ideally we’d like to delegate all of the styling to files that we could put under version control, yet this is a case where we found that approach to be very convenient.

Another viable option would have been to identify all the possible combinations of column/row starting/ending points, and programmatically map those with classes that could then be used to actually position elements within the grid. On a 12×6 grid, that would have lead to having a grand total of 36 class selectors, looking like this:

.grids-cs-1 {   grid-column-start: 1; }  .grids-ce-2 {   grid-column-end: 2; }

What if we decide to offer more control over how a grid is composed and, say, give users access to options that determine how many columns or rows form the grid structure?

We’d have to manually map the classes that we don’t yet have in the stylesheet (and release an update to the plugin just for that), or, again, generate them inline, and then add those classes to the grid elements.

While perfectly fine, this approach kind of goes against the idea of having a leaner, more scannable markup, so we’ve decided not to follow this route, and pay the price of having style dynamically put in the head of the document, knowing that it could be easily cached.

Because of the experimental nature of the plugin, the backend UI that’s being used to actually compose the grid is created with CSS Grid, and a set of CSS variables through which we control the properties of content Areas. Using variables has immensely sped up our work behind the grid creator prototype — had we chosen a different path there, things wouldn’t just be much longer in terms of development times, but also more complex and less clear to maintain down the road.

Feedback wanted!

To further foster the adoption of CSS Grid, we need tools that automate the process of creating layouts with it.

While we have been seeing great examples of this technology out in the wild, it would be short-sighted to assume that every website that is published today has a team of front-end devs behind it, that can take care of the issue.

We need tools that produce good markup, that don’t hinder the maintenance of the website stylesheets, and, most importantly in the WordPress world, that can be easily integrated with the existing themes that people love to use.

We think Grids is a step forward in that direction, as it’s a tool that is built upon two standards — the Block Editor API, and CSS Grid — and, as such, suffers less risk of reinventing the proverbial wheel.

While we’ve been recording general interest in the plugin at the recent WordCamp Europe in Berlin – with Matt Mullenweg himself displaying a brief demo of the plugin during his keynote — we know that it still needs a lot of feedback that can only be obtained with real-life scenarios. So, if you want to take Grids for a spin, please use it, test it and, why not, suggest new features.

The post Bringing CSS Grid to WordPress Layouts appeared first on CSS-Tricks.


, , ,

Look Ma, No Media Queries! Responsive Layouts Using CSS Grid

Not only has CSS Grid reshaped the way we think and build layouts for the web, but it has also contributed to writing more resilient code, replacing “hacky” techniques we’ve used before, and in some cases, killing the need to rely on code for specific resolutions and viewports. What’s so cool about this era in web development is that we’re capable of doing more and more with fewer lines of code.

In this article, we’ll start dipping our toes into the power of CSS Grid by building a couple of common responsive navigation layouts. It’s easier than what you may think, and since CSS Grid was built with responsiveness in mind, it’ll take less code than writing media queries all over the place. Let’s do this!

Layout #1: Hero content and list of articles

See the Pen
Hero Content and List of Articles
by Juan Martín García (@imjuangarcia)
on CodePen.

We’ll kick off this set of examples by creating a common website layout: A full-width hero section, with a grid of cards below.

Both elements will respond to window resizing and adapt accordingly. Though this might seem like a lot of code at first glance, the responsive behavior is done with only six lines of CSS Grid code, and without writing a single @media rule. Let’s break down the code to see what’s going on:

The hero section

Let’s take a look at the code for the .hero element:

<section class="hero">   <h1>You thirsty?</h1>   <article>     <p>Explore local breweries with just one click and stirred by starlight across the centuries light years great turbulent clouds circumnavigated paroxysm of global death.</p>     <a href="#breweries">Browse Breweries</a>   </article> </section>
.hero {   /* Photo by mnm.all on Unsplash */   background: url('https://images.unsplash.com/photo-1518176258769-f227c798150e') center;   background-size: cover;   padding: 4rem 2rem;    /* Grid styles */   display: grid;   align-items: center;   grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

We have a bunch of background styles to enable the beer background, a bit of padding to separate the content from the edge of the screen, and then three lines of grid styles:

  1. The first line (display: grid;) is changing the behavior of the .hero element to be a grid container. That means the elements inside .hero are now grid items.
  2. The second line (align-items: center;) is going to vertically center the columns on our grid. But these two lines don’t do anything on their own until we set the columns of our grid.
  3. And that’s where the third line comes in. A lot of stuff is going on in that single property, so let’s go one step at a time.

The repeat() function

Generally speaking, what we usually do to define our columns and rows on a CSS Grid is to add the value for each track after defining the property, like this:

.element {   /* This will result on four columns, each one of 1fr */   grid-template-columns: 1fr 1fr 1fr 1fr;   /* This will result on two rows, each one of 300px */   grid-template-rows: 300px 300px; }

Now, that’s quite dull. We can use the repeat() function to make that less verbose and easier to follow. The function takes two parameters:

  1. The number of times to repeat the value.
  2. The value itself.

After refactoring our code to use repeat(), we should expect the same results from these lines of code:

.element {   /* this is the same as grid-template-columns: 1fr 1fr 1fr 1fr; */   grid-template-columns: repeat(4, 1fr);   /* this is the same as grid-template-rows: 300px 300px; */   grid-template-rows: repeat(2, 300px); }

Much cleaner, yeah?

The minmax() function

Now, the above examples are explicitly defining sizes for the tracks (1fr and 300px). That might work for some scenarios, but for our beer example here, we need to be able to automatically calculate the size of the track, based on the width of the viewport, and automatically adjust the number of columns shown. To be able to do that, we’ll define a range of values using the minmax() function. What will we be defining? You’ve probably guessed by now: The *minimum* and *maximum* values we want these columns to be able to resize to.

In the hero for our beer example above, we set our minmax() property to be 240px at its minimum size, and 1fr at its maximum size. fr units, if you’ve never heard of them, stand for fractional units. Nobody can explain them better than Jen Simmons on this video and Robin Rendle in this post.

Using the Firefox Grid Inspector to check the change on the track’s size when resizing

That results in our tracks being 1fr when there’s plenty of space on our viewport (aka desktop resolutions), and 240px when there’s not enough space for both columns (like on mobile devices). That’s why they nicely grow when we make our browser wider, since they’re taking the remaining space and equally dividing it across the existing columns. Now, moving to the last piece of the puzzle!

The auto-fit keyword

The auto-fit keyword allows us to wrap our columns into rows when there’s not enough space in our viewport to fit the 240px minimum value without overflowing the content. Sara Soueidan wrote an excellent article about auto-sizing columns using the auto-fill and auto-fit keywords, in case you want to dive a little deeper into what’s going on under the hood. Now, with that last bit of code in place, we should be able to achieve this result:

The column is automatically wrapping when there’s not enough space in the viewport

The article list

Now that we’ve thoroughly reviewed the behavior of the elements inside our hero element, it’s likely that the first two lines of CSS code for the breweries list below it might already seem familiar to you:

.breweries > ul {   display: grid;   grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));   grid-gap: 1rem; }

That’s right! We’re using the exact same approach: On the first line we define our grid, on the second one we size our tracks using the same magic one-liner, and on the third line we set a gap for these columns. Nothing new under the sun, and what’s really neat about this, is that our code is resilient enough to adjust the number of tracks and their sizes, according to the number of items we have inside our unordered list:

The grid responds to the change in the number of tracks, and adapts the layout

That’s all, folks! A fully responsive website layout, using just six lines of CSS code. Not bad, huh? Make sure you check the source code and play around with this example on CodePen.

Layout #2: Full-width image gallery

See the Pen
Full Width Image Gallery
by Juan Martín García (@imjuangarcia)
on CodePen.

On this next example, we’ll embrace the power of our newly learned combination of repeat(), auto-fit and minmax() to create this responsive image gallery. We’ll also be sizing our tracks using grid-column and grid-row, and learning about the handy property:value combination of grid-auto-flow: dense; that allows us to change the default behavior of the elements that can’t fit on our explicit tracks: Instead of wrapping themselves in new rows or columns, we’ll make them fit into the unused spots on our grid. Let’s get into the coding!

The grid setup

The grid is created using our familiar display: grid; property, where columns are defined using repeat(), auto-fit and minmax(). We also added a bunch rows with a repeat() function and defined a gap to our images, using grid-gap. But the new player here is the grid-auto-flow: dense;. We’ll get to it in a second.

.gallery > .gallery__list {   display: grid;   grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));   grid-template-rows: repeat(6, 200px);   grid-gap: 1rem;   grid-auto-flow: dense; }

We also created a repetition pattern using the nth-child() pseudo-selector to set different sizes for our tracks using grid-column and grid-row. Notice here that we’re using the span keyword to allow the selected item to occupy more than one column or row.

/* This will create 2x images every 4 elements */ .gallery > .gallery__list > li:nth-child(4n) {   grid-column: span 2; /* Spans two columns */   grid-row: span 2; /* Spans two rows */ }  /* This will create 3x images every 8 elements */ .gallery > .gallery__list > li:nth-child(8n) {   grid-column: span 3;   grid-row: span 3; }

And finally, we’ll make sure our images cover the entire area of its container, regardless if it’s 1x, 2x or 3x, using object-fit: cover;. If you have never heard of object-fit, it works fairly similar to how background-image does, but with HTML <img> tags:

.gallery > .gallery__list > li > figure > img {   width: 100%;   height: 100%;   object-fit: cover; }

Now, the real deal here is grid-auto-flow: dense;. Check what happens when we take that out from our code:

Removing grid-auto-flow: dense; leads to inconsistent placement of the elements on the grid

See those holes on our beautifully crafted grid? That’s because some of the elements on it are taking 2x or 3x spots, and when there isn’t enough space on our tracks to fit them, they’ll wrap into a new row, since that’s the default behavior. By changing it from row to dense, we’re telling the grid to fill any gaps we might have with elements that could fit them, regardless of their source order on the DOM.

That’s why this technique might come especially handy for things like image galleries, but might not be suitable for other use cases where you might need to preserve the order of the markup. Feel free to play around with the CodePen demo to check the differences between where items are placed.

Layout #3: Trello-style card layout

See the Pen
Trello-Style Card Layout
by Juan Martín García (@imjuangarcia)
on CodePen.

Now, on to the last demo, where we’ll take advantage of the ability to nest grids to recreate this Trello Board. We’ll be creating a grid to hold our four different columns, and inside of those, we’ll create a child grid for our cards. Even though this example won’t explore new properties or revolutionary methods, it’ll help us to get a grasp on how easy it is to build complex layouts with a few lines of CSS code. This demo has a lot of extra code to achieve the styling of the Trello layout, so we’ll focus solely on the grid styles.

The columns

To create the four columns, we’ll use display: grid; on the container and use our magical one-liner for our grid-template-columns. We’ll also be defining a gap between them, and use align-items: flex-start; to ensure that our columns don’t stretch to the bottom of the screen.

.column__list {   display: grid;   grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));   grid-gap: .5rem;   align-items: flex-start; }

Now, the original Trello is not responsive by default: If you resize your browser on a Trello Board, you’ll notice that you’ll end up having a horizontal scroll on your columns, rather than wrapping them on a new row. We’re not following that behavior here since we want to build responsive layouts, but in case you’re curious, and want to emulate Trello’s functionality, you can achieve that by adding two more lines of CSS code:

.column__list {   display: grid;   grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));   grid-gap: .5rem;   align-items: flex-start;   /* Uncomment these lines if you want to have the standard Trello behavior instead of the column wrapping */   grid-auto-flow: column;   grid-auto-columns: minmax(260px, 1fr); }

We learned about grid-auto-flow in our previous demo and discovered that it let us control how the auto-placement algorithm work, and how implicit elements should be added in the flow of the grid. The default behavior is row, meaning that any extra element that won’t fit on our grid will wrap into a new line. We changed that to be dense on our previous demo, and we’ll change it to be column on this one: That way, any new column added here will end up in an implicit column, and have a horizontal scroll. We’ll also define a width for those auto-generated columns with the grid-auto-columns property.

Modifying the grid-auto-flow property will make this demo behave like the real-world Trello

The cards

For the cards grid, we’ll use a similar approach. We’ll display: grid; on the container. We won’t define any columns here, since we don’t want to have any, and we’ll put grid-template-rows: auto; to use to avoid all cards having the same height — we want some of them to be bigger and some of them smaller, based on the type of content being added to them.

.card__list {   display: grid;   grid-template-rows: auto;   grid-gap: .5rem;   margin: .5rem 0; }

And, again, that’s all folks! Two more lines to set a gap and a margin to the cards, and we’re done! Everything else in the Pen is standard CSS to achieve the Trello look and feel.

So then… are media queries dead?

Back in the day, when we were building layouts using display: inline-block or floats, media queries made a lot of sense in order to change the size of our elements as the viewport got smaller. But now, with the incredibly powerful layouts that we’re able to create with a couple of CSS lines, you might feel tempted to think that media queries are doomed. I strongly disagree with that: I believe that we should change the way we think about them, and therefore use them differently.

As Rachel Andrew stated about a year ago, we should use media queries to fix our layout when it breaks, rather than targeting devices: There are so many out there! With the advent of Media Queries Level 4 and 5, we’re not only able to detect screen sizes now, but pointer types as well. As a result, we can dig into a user’s system preferences and adapt our code for those who prefer reduced motion or whether we should use inverted colors. That means media queries are not dead; on the flipside, I’d say it’s an exciting time for using media queries, but we need to learn to use them right. In the meantime, building robust layouts using modern techniques such as Flexbox or CSS Grid, will save you a bunch of time, code, and headaches.

The post Look Ma, No Media Queries! Responsive Layouts Using CSS Grid appeared first on CSS-Tricks.


, , , , , ,

Algorithmic Layouts

Don’t miss this video by Heydon that digs into CSS layouts. It’s great how he combines fundamental knowledge, like the way elements flow, wrap, and can have margin with new layout methods like flexbox and grid (with specific examples). Of particular note is the clear demonstration of how flexbox and grid help avoid the need to constantly intervene with media queries in order to affect responsive layouts.

So, in place of this…

.sidebar {   float: left;   width: 20rem; }  .not-sidebar {   float-right: calc(100% - 20rem); }  @media (max-width: 40rem) {   .sidebar, .not-sidebar {     float: none;     width: auto.   } }

…something like this:

/* Parent container */ .with-sidebar {   display: flex;   flex-wrap: wrap; }  .sidebar {   flex-basis: 20rem;   flex-grow: 1; }  .not-sidebar {   min-width: 50%;   flex-grow: 600; }

This isn’t a one-off video either, Heydon’s channel has videos on making unusual shapes and custom properties as well.

Direct Link to ArticlePermalink

The post Algorithmic Layouts appeared first on CSS-Tricks.