Checkout my Getting Started with React video course on Skillshare. It is 100% free.

The CSS grid minmax() function explained

What if we have a scenario where we need a layout made of 3 columns with the following behavior:

  • the first column can go anywhere from 100px to a maximum of 300px, depending on the screen of size of the screen
  • the second and third columns will take 50% each of the remaining space.

So, for example, if we have a screen of 700px with then the first column will take 300px, while the next two columns will have 200px each.

The tricky part is defining the size of the first column. Well, this is what the minmax() function is made for. You give it a max and min value and that column / row will not exceed or go below those sizes.

For our case we will have the folwing:

.container {
    display: grid;
    grid-template-columns: minmax(100px, 300px) 1fr 1fr;
}

Of course, the first value can not be smaller than the second one.

We can apply it also to the rows. So if we want to set a minimum height for the rows we can say:

.container {
    grid-auto-rows: minmax(50px, auto);
}

Take a look at this codepen for the full example:

See the Pen
minmax
by JS Craft (@js-craft)
on CodePen.

Making a full example with CSS grid – the calculator pad

I had a bit too much time at my disposal this weekend and played with an example on codepen. I've ended up with this CSS grid layout, something like a calculator pad:

If you scroll at the end of this article you can see the full code of the example. A few notes about the CSS code:

1. everything is done with the CSS grid and the grid template areas

2. in the grid template areas if we want to skip one element we can use the .. For example, with this line:

 grid-template-areas: 
   /* ... */
    ".   zero .   enter";

we will generate this row:

3 one fantastic thing about the CSS grid is that you can fully control the position of an element in the design independent of its position in the HTML. For example, even if in the HTML we have:

<div class="one">1</div>
/*....*/
<div class="tens">9</div>

in the design, we can put the digit 9 before the digit 1 by just adjusting the template areas.

4. to define the number and size of the rows and columns I've used the grid repeat function.

5. the button pressed effect was made from a combination of the :active, :hover and the scale transform.

.grid-container>*:hover {
  background: #003554;
}

.grid-container>*:active {
  transform: scale(.95);
}

So, here is the full example. Enjoy, and if you have questions email me at daniel [at] js-craft.io.

See the Pen
digidpad
by JS Craft (@js-craft)
on CodePen.

A few considerations about the CSS min-width, width, and max-width properties

In theory, things should be pretty staring forward with the min-width, width, and max-width properties:

  • min-width will tell that an element it cannot be narrower than a specific value
  • width will tell that the element will always have a fixed width
  • max-width will tell that the element will not be wider than a specific value.

However, what happens if we have some conflicting values like:

.my-element {
    min-width: 300px;
    width: 500px;
    max-width: 100px;
}

Well, the general rule is that the min-width property overrides both the width and max-width properties and prevents the value of the width from becoming smaller than a specified value.

Alongside max-width and min-width we also have max-height and min-height so all that it is said about the width properties is also available for the height props.

Using percentages for min-width and max-width

One tricky (and useful) use case is when we use percentages to express the values for the max and min-width.

Having the width:100% means that we use the parent's width to calculate the current width value whereas max-width:100% uses the original width to calculate the maximum size.

So, let's say we have a jpg image file with a real width of 100px that it is placed in a div with a width of 200px. If we will have img { width:100%; } then this means that that the jpg image will be stretched to 200px.

While having img { max-width:100%; } means that the img will to its natural maximum of 100px. Check out the below codepen:

See the Pen
min-max-taz
by JS Craft (@js-craft)
on CodePen.

Passing a CSS variable value from the HTML into the CSS

One nice trick I've discovered recently is that you can "pass" the value from the inline HTML to the CSS by having something like this:

<div style="--main-color: red;">RED</div>
div { background-color: var(--main-color); }

I've used quotes when saying to pass because we are not actually passing that variable. We are just defining an inline style for that element and we will let the cascading of the CSS do the rest.

In some scenarios, this is cool because we can define properties for some HTML elements as we would have done with something like React properties.

Of course, we can also add in the :root element a default value for the CSS var.

Below you have the full working codepen.

See the Pen
CSS Var pass value
by JS Craft (@js-craft)
on CodePen.

Speaking about the CSS variables I've written some time ago a more in-depth article about them that you can read here.

Stacking elements on top of each other with CSS grid

Even dough I don't believe the CSS grid was designed especially for stacking elements one on top of each other this can be achieved easily with a combination of grid-area and z-index.

Let's say we want to build the below widget.

This can be described by the following HTML structure:

<div class="card">
    <div class="top">A cat named</div>
    <div class="bottom">TOM</div>
    <img src="http://examples.js-craft.io/tom.png" alt="TOM">
</div> 

If we place it in grid layout of 1 column - 3 rows then we can easily say something like:

.card { display: grid; }
img {  grid-area: 1 / 1 / 4 / 2;  }
.top { grid-area: 1 / 1 / 2 / 2; }
.bottom { grid-area: 3 / 1 / 4 / 2; }
.card div { z-index: 2; }

That's pretty much all that we need to stack elements on top of each other with the CSS grid. Just don't forget to set the z-index prop to the elements you want on top and that the grid-column is using line numbers to place items. Therefore that's the reason why we have lines like img { grid-area: 1 / 1 / 4 / 2; } even if we have just 1 column and 3 rows.

Below you have the full working example:

See the Pen
tom-cat
by JS Craft (@js-craft)
on CodePen.

My top “eureka” moments while learning CSS

There were defining moments in our evolution as a species. Like when we discovered fire, or when we discovered electricity. Exactly like this, we have some breakthrough moments when we learn something new.

In its essence CSS is simple. We have selectors and properties that we combine to style our HTML documents.

However, there are still moments when I've felt like I have discovered that missing piece of the puzzle that was explaining why things were not behaving as intended.

So, my main breakthrough moments:

1. The CSS box model: In the beginning, it was not clear to me that if you have an element with width: 100px and border: 5px solid that element will need in total 110px of space. Things like the border, margin, and padding are not included in the width of an element. And we can change this with the box-sizing property .

2. How CSS deals with conflicting rules: What if we have:

html div p {color: blue}
body p {color: red}

What color our paragraphs will be? The two main principles that are used by CSS to decide the winning rule are specificity and cascading. Of course initially I was getting frustrated and was using !important all over the place. But getting a grip on how these principles work made writing CSS a more enjoyable experience.

3. Using CSS grid and flexbox: layout is hard in CSS. Maybe the most complicated subject. However, with the addition of CSS grid and flexbox things got way better. What took before a lot of math and "brainpower" become simpler with these two. You can see here also a way on how to decide when to use the CSS grid and when to use flexbox.

Of course, every learning experience is unique, but for me, these were the things I wished somebody told me when I've started making stuff with CSS.

Cheers and happy learning!

Using computed property names with console.log

Let's say we have the following code:

const tom = { name: 'Tom', colour: 'blue and white' }
const pib = { name: 'Puss in Boots', colour: 'orange'}
const syl = { name: 'Sylvester', colour: 'blue and white' }

console.log(tom) // { name: 'Tom', colour: 'blue and white' }
console.log(pib) //  { name: 'Puss in Boots', colour: 'orange'}
console.log(syl) // { name: 'Sylvester', colour: 'blue and white' }

By using the computed property names in Javascript we can have all the console.log statements combined into just one line.

console.log({ tom, pib, syl }) // {tom: {…}, pib: {…}, syl: {…}}

Quite a useful trick for when you want to console.log the full context of a piece of code.

Here and here you can find two more articles with tips when using the js console.

Using grid-area to span an element across multiple CSS grid cells

Let's say we want to build the example below:

Defining the grid can be easily done with the repeat function:

.container {
    display: grid;
    grid-template-columns: repeat(3, 75px);
    grid-template-rows: repeat(3, 75px);
    grid-gap: 5px;
}

All the elements (besides the green one) take only one cell, so placing them it's quite straight forward with something like:

.red {
    grid-row: 3;
    grid-column: 1;
}

Now, the tricky part is with the .green element. To make it span across multiple cells we have a few ways of doing it. We can use grid-row-start and end or we can use the span keyword.

For me, the most intuitive approach is by using the grid-area property. How it works is by giving it the coordinates for the top-left cell and the ending bottom-right cell.

The element will span all the way from the top-left to the bottom right. However, keep in mind that the actual bottom-right cell is not included so we will have +1 for the ending coordinates.

So, in our case if we want the green cell to go from cell 1-1 to cell 2-2 we will have:

.green {
    grid-area: 1 / 1 / 3 / 3;
}

The full documentation about it property can be found here.

You can see the full working codepen below.

See the Pen
grid-area
by JS Craft (@js-craft)
on CodePen.

EXTRA TIP: if you add one element in a CSS grid but you don't specify where you want that element to be placed the grid will place it in the first available cell that is found by traversing top-left to bottom-right. The next one in the next available cell and so on. This is the reason why we did not need to manually place the blocks that take just 1 cell (.red, .blue etc).