Flex items and min-width 0

Earlier I wrote about using flexbox to build responsive layouts. There is a behavior that can be surprising when using flexbox for layout like this. The content of a flex item in the layout can force it to not shrink appropriately. Let’s say for example you have a long URL displayed somewhere in your layout that you want to truncate. Applying overflow: hidden will not result in the item shrinking like you may expect it to. You can see an example in this codepen when resizing your browser.

This may appear as a bug, but it is actually a part of the spec for flexbox.

In the spec it says:

By default, flex items won’t shrink below their minimum content size

This means the minimum width of an item is set to the width of its content and it won’t shrink past that width. This can result in layouts appearing uneven or wrapping too early. By adding min-width: 0 to the item, it will resize at the correct ratio and still apply the overflow as desired. You can see an example here.

For more reading on this issue and others related to flexbox see this list of known bugs and the w3 spec.

Wrappable content with flexbox

Although specifying widths and proportions for layout items works, sometimes you need those widths to be based on the content rather than specific values. Sometimes we won’t know how long our content will be. This is where having a layout that responds to its content is handy.

Let’s say for example we want to create a list of items. We want the title of the item on the left, and the content for the item on the right. We would prefer if these items stay on one line, but if they don’t have enough room, the title should go above the content.

We will start with this markup

<section class="item">
  <div class="item__title">
    <h2>Item title</h2>
  </div>
  <div class="item__content">
    <p>Item content</p>
  </div>
</section>

We will now apply a little flexbox magic to get the wrapping we want. First we setup the item class as our flex container.

.item {
  display: flex;
  flex-wrap: wrap;
}

We want the title to only take up as much space as it needs to we set the flex-grow and flex-shrink properties to 0 with the shorthand flex: 0 0 auto.

.item__title {
  flex: 0 0 auto;
}

The content should take up whatever space is left so we set the flex-grow and flex-shrink properties to 1 with the shorthand flex: 1 1 auto.

.item__content {
  flex: 1 1 auto;
}

So far, this is great. If our content is too long, it will simply wrap underneath the title. No need to set arbitrary widths or breakpoints to do it either.

But wait, let’s say we want some margin in between the title and the content. The problem is, if we add margin to the left or right, it will still be there when it wraps. Luckily there is a bit of a hack we can do to get around this.

First, we add some negative margins to our item flex container.

.item {
  display: flex;
  flex-wrap: wrap;
  margin-top: -20px;
  margin-bottom: -20px;
}

We then add margins on the flex children to counteract the negative margins on the container.

.item__title {
  flex: 0 0 auto;
  margin-bottom: 20px;
  margin-left: 20px;
}

.item__content {
  flex: 1 1 auto;
  margin-bottom: 20px;
  margin-left: 20px;
}

Now our item can have 20px of margin between the title and the content, but when it wraps it will still be flush with the edge of the item.

We also may want vertical margins between two items. To do this we add another rule to our CSS.

.item + .item {
  margin-top: 20px;
}

This will add margin to the top of any item that is directly following another item in the DOM.

So there we have it. A simple way to wrap our layout based on the content within it. It allows us to use a fairly generic structure for all different lengths of content and still have it look nice.

Check out this codepen for an example of this in action.

Building a CSS component with BEM

This article will walk you through creating a simple component in CSS.

Why a component?

As your CSS for a project gets larger, a single CSS file with random selectors will become more and more difficult to navigate. It may also cause you to run into issues with specificity as you add more complicated selectors to target elements. You will need a way to organize this to make it reusable and allow it to scale.

This is why many developers believe it is best to split your CSS into separate components that have specific purposes using a modular approach like BEM or SMACSS.

For example, let’s say we want to create a new way to alert users with some information. Sometimes it will be just generic information, but other times it will be an error or success message. We will start with some simple markup.

<div class="alert"></div>

In BEM the B stands for block. The block is just the base class of the component. In this case we will use the class alert as the base. We use that class to add some styling to the default alert.

.alert {
  background: DeepSkyBlue;
  border: 1px solid DodgerBlue;
  color: white;
  padding: 20px;
}

This message should have a title, so we add a new heading to our markup with the class alert__title. The double underscore here signifies that the title element belongs to the alert component. In BEM the E stands for element, but this can also just be thought of as a sub-component.

<h2 class="alert__title">Alert</h2>
.alert__title {
  font-size: 1.2rem;
  font-weight: 300;
}

Because the selector is just a single class, it doesn’t add any extra specificity. This helps to avoid issues when trying to overwrite rules later on.

The other nice thing about the selector is that we can easily change the element if needed. Say we decide these titles should be h3s instead of h2s semantically. We can simply change the heading level and the styling will still work.

We also want this alert to have a more detailed message so we add another new sub-component. We use the class alert__message for this.

<p class="alert__message">Details alert message</p>
.alert__message {
  font-size: 0.9rem;
  font-weight: 400;
}

But we don’t just want to use the alert for basic information, we also want to use it to display errors to the user. To do this we create a new variant of our alert component. In BEM the M stands for modifier. We use the class alert--error because the two hyphens signify it is a modifier on the component. Modifiers can be used to create new variations of a component.

<div class="alert alert--error">
  <h2 class="alert__title">Error</h2>
  <p class="alert__message">Error message.</p>
</div>
.alert--error {
  background: Crimson;
  border-color: FireBrick;
}

You will notice we use both the alert class as well as alert--error. This allows us to inherit the text color and padding styles from a default alert, but also overwrite with the background and border color we want for an error. Notice we use border-color here as to not overwrite the other border properties as well.

We can also have multiple modifiers for a component. Let’s say we also want to display a success message to the user. We add another variant to the component to accomplish this.

<div class="alert alert--success">
  <h2 class="alert__title">Success</h2>
  <p class="alert__message">Success message.</p>
</div>
.alert--error {
  background: YellowGreen;
  border-color: LimeGreen;
}

So there you have it. A simple component that is flexible and can be reusable in your markup. You can see an example in this codepen.

This same concept can be applied to all the pieces of your design system as you build them. Although all the hyphens and underscores in BEM may seem wacky at first, they will make it easier to parse mentally when looking at them. You may find it cumbersome at first, but you will thank yourself later on.

Build for the future.

Prioritizing layouts with the order property

In my last post I wrote about building responsive layouts with flexbox, but we can take it one step further and use the order property to help prioritize those layouts.

Let’s pretend we have a fairly typical two column layout with a sidebar on the left, and a section for the page content on the right.

We start with some simple markup.

<div class="layout">
  <aside class="layout__sidebar"></aside>
  <main class="layout__main"></main>
</div>

Then we add the following CSS to get a working responsive layout.

.layout {
  display: flex;
  flex-wrap: wrap;
}

.layout__sidebar {
  flex: 1 1 200px;
}

.layout__main {
  flex: 20 1 600px;
}

We set the main column to flex: 20 1 600px. That is shorthand for flex-grow: 20, flex-shrink: 1, and flex-basis: 600px. The flex-grow will make the main column grows 20 times more than the sidebar, which causes the sidebar to almost stay the same size. The flex-basis of 600px is so that it will wrap when it shrinks below that width.

Here is an example codepen. Try resizing your browser and notice how the sidebar goes above the main content on smaller screens. This may be fine for some designs, but let’s pretend the sidebar content isn’t that important and we don’t want it to be the highest priority on smaller screens.

This is where we can allow the order property to work its magic.

First, let’s rearrange that markup we had created to look like this.

<div class="layout">
  <main class="layout__main"></main>
  <aside class="layout__sidebar"></aside>
</div>

We change the order in the DOM so that by default the sidebar will come after the main content. We can then use the order property to change the visual order on larger screens.

Then we create a breakpoint at the width where our layout will wrap. This will be the sum of the sidebar flex-basis (200px), and the main content flex-basis (600px). This is even easier if we are using a preprocessing language like LESS or Sass because we can create variables for these values and then add them automatically for the breakpoint.

Finally, we change the order of both the sidebar and main column using the order property.

@media (min-width: 800px) {
  .layout__sidebar {
    order: 1;
  }

  .layout__main {
    order: 2;
  }
}

Now when we resize our browser the sidebar will be to the left of the main content when there is enough space, and underneath on smaller screens. You can see a working example in this codepen.

Hold up, are you sure this is a good idea?

This is a useful technique and can be a big help when it makes sense to reorganize content at different screen sizes, but it should be used with caution.

There are some drawbacks to only reorganizing content visually, and not the actual DOM elements themselves. Unexpected tab order may be confusing to users. Even though an input appears to come before another, it could actually be reversed in the tab order.

Still, in some cases that makes sense anyway. So like Spider-Man once said, “with great power, comes great responsibility”. Use it responsibly.

Update

Chris Sauvé pointed out to me that this can also be accomplished without any media queries using flex-direction: row-reverse. Check out his codepen to see it in action.

Responsive layouts with flexbox

Recently I have been playing around with some new ideas for responsive layouts. Typically one would probably set some breakpoints and use media queries throughout their CSS to change the layout at different screen sizes. This works, but you can also end up having many different breakpoints that can be difficult to manage. An alternative approach is to use flexbox with the flex-wrap property and let the component or content dictate how it fits into the layout.

Let’s assume we have this markup for a two column layout.

<div class="layout">
  <div class="layout__item"></div>
  <div class="layout__item"></div>
</div>

First, we allow the flex container to wrap its children as needed.

.layout {
  display: flex;
  flex-wrap: wrap;
}

Then we specify the preferred min-width of the children using the flex-basis property. We also allow the items to grow and shrink as needed.

.layout__item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 200px;
}

Or even better, we can shorten this to one line using the shorthand flex property.

.layout__item {
  flex: 1 1 200px;
}

With just these few lines of CSS we already have a working responsive layout. The key here is the flex-basis that is being set to a specific width. This allows the item to wrap when it can’t fit into that minimum size that it prefers. This is also nice because when it does wrap, it can still stretch to fill the container. Our component can now dictate the space it requires and respond correctly to fit itself into the layout. We also don’t even need any media-queries to do it. Neat.

You can see the working example on codepen.

Reflecting on 2015

Looking back on 2015, it had some big changes in it for me, and with that came some challenges. The biggest change was making the move from my old job to work for Shopify. I have been working there almost a year now and it has been a truly amazing experience, even if it has been uncomfortable at times. I find the more I put myself out of my comfort zone, the more I am learning. It is amazing how you can surprise yourself every day when you simply push yourself to try new things. My failures have taught me just as much, if not more, than my successes.

When I first got to Shopify I was intimidated. I looked around and saw so many smart people across all of the company. Experts in their own domains, who were truly passionate about their crafts. It was hard to know how I could possibly be of any real value to a team as talented as this.

What I have come to realize though, is that the more you absorb and learn from those people, the more value you can add to your team. The more you are exposed to ideas and opinions, the more you can grow yourself. Each individual can bring a perspective that can impact a product. Everyone is valuable in the collective experience they bring to any discussion.

Big problems can’t always be solved by one person.