Archiwum kategorii: CSS

Random Day in the Life of a Developer

Post pobrano z: Random Day in the Life of a Developer

Yesterday, I started going through my email as soon as I got to work. I always start my day with email. I kinda like email. I read some interesting things in keeping up with the industry. I deal with some business things. I handle with some personal things. I make a note of the most important stuff going on.

Then I kept working!


I fixed a bug that was affecting Firefox exclusively. This code would set some elements in a row with flexbox, let them wrap, then looked at all of them to see which ones wrapped and which ones didn’t. Then it put the ones that wrapped in an overflow menu. Seemed simple enough. But some of the items were in bold text and some were not. The ones that were not bold were somehow pushed down 1.5px in Firefox (but in no other browser I looked at). The code checked to see if the top position was anything higher than 0 in order to check if they wrapped, and thus incorrectly marked some elements as being wrapped. The code had to be loosened up to accommodate that.


I tweeted some things that looked particularly interesting that day.


I had logged a bug a few days ago where a couple of small buttons were not styled or aligned how they should be in a common modal dialog. In diagnosing the issue, it looks like we had a weird git merge where some newer CSS was merged in that was assuming some HTML that wasn’t quite live yet.

I decided the cleanest way forward was to make the small HTML change forthcoming in the new branch in a new fixer branch that could go out quickly. The alternative was reverting the CSS back and my guess was that would have caused worse merge conflicts later, plus it was worth taking advantage of the newer, nicer styling now.

Then, because of course it did, the small HTML change caused another bug. The JavaScript that was watching those buttons couldn’t find them anymore and I failed to test it or, ideally, write a test for it. So, I had to fix that too, but sadly only after a user reported it. Gosh, I gotta improve our integration tests there.


I was in two meetings. One was a standard weekly catchup meeting. One was with a new person I’d never met before and we were exploring if there was an interesting way we could work together.


I fixed a bug with some bad backend logic (that I had written myself, of course). I wanted to display some information to a user based on, I thought, if they were on a team or not. I got that logic right, but it turns out the messaging was depended on that team being active (i.e. not expired in some way), so I had to update the logic to account for that. My team member helped me think it through because I didn’t understand the way billing and active subscriptions were tied to the user well enough.


I fixed a bug where a UI element was showing a strong warning state, but there was no way to find out what the problem was. It was a big red box with an exclamation point in it. It even had a hover state. But clicking it did nothing.

Turns out it was just a problem with event delegation. It was being added to the page after click handlers attempted to bind two elements like that. I fixed it by re-binding those click handlers after of the error UI was appended. It didn’t feel great. A better fix might have been updating the event delegation to be more efficient about this case. But, I’d been burned by that in the past, so this fix seemed more robust, even if less elegant and efficient.

It made me pine for the page being ported to React, where a silly event delegation bug would have never been an issue. Not long after, I fixed another bug where a click handler had been bound to a span.class_name, and the span was updated to be a button. That was a semantic and accessibility win, but broke the handler.

Again, something that just doesn’t happen in React.


Then I wrote this blog post and went home.

The post Random Day in the Life of a Developer appeared first on CSS-Tricks.

Delivering WordPress in 7KB

Post pobrano z: Delivering WordPress in 7KB

Over the past six months, I’ve become increasingly interested in the topic of web sustainability. The carbon footprint of the Internet was not something I used to give much thought to, which is surprising considering my interest in environmental issues and the fact that my profession is web-based.

The web in a warming world

As a brief recap, I attended MozFest in London last year. In between sessions, I was scanning a noticeboard to see what was coming up, and I spotted a session entitled, „Building a Planet-Friendly Web.” I felt a little dumbstruck. What on Earth was this going to be about?

I attended the session and the scales fell from my eyes. In what now seems obvious — but at the time was a revelation — I learned of the colossal energy demand of the Internet. This demand makes it the largest coal-fired machine on Earth, meaning that its CO₂ emissions are probably at least equivalent to global air travel. More and more people are coming online, but this, coupled with the rise of ever more obese websites, means that the Internet’s energy demands are growing exponentially. Every additional byte transferred means more energy, which in most countries means more CO₂.

It is widely accepted that we should avoid printing emails to save trees, but this leads to a false assumption that the web is a green medium. I’m afraid to say, it is not.

Is there another way?

The good news is, it needn’t be this way. Since 2009, Greenpeace has been auditing Internet companies on their energy usage, and lobbying them to improve by way of their Clicking Clean campaign. The Green Web Foundation has an ever-growing database of hosting companies who use renewable energy, or who are at least committed to being carbon neutral. And new tools are emerging to help those working on the web measure the environmental impact of our products.

There are also some great resources out there such as Tim Frick’s Designing for Sustainability, three year’s worth of talks from the SustainableUX conference, and peripheral material that, while not explicitly focused on sustainability, can help us build lower carbon websites.

Enter Susty WP

I decided to challenge myself to see how efficiently I could package a WordPress website. While I was at it, I thought, “Why not make the website about sustainability and WordPress?” I know, WordPress/sustainability inception. Cool, huh?

And so, sustywp.com is born. With its accompanying theme, Susty. I’m rather chuffed to say I managed to get the load of the homepage down to 7KB of data transfer. I did actually get it down to 6KB, but the meta stuff added by Yoast bumped it up almost a whole KB! 😛 However, given I’m trying to spread a message, I deemed this to be an acceptable trade-off.

Before I get into the nuts and bolts, I just want to share a few headline facts:

So, how does it work?

The remarkable thing about this is actually how mundane it is. Heavily inspired by Heydon Pickering’s evangelizing about writing less damn code, and projects like Brad Frost’s Death to Bullshit, I embarked on a root and branch pruning of Underscores, removing everything I possibly could. And to be clear, it’s not as though Underscores is full of cruft. It’s a very lean starting point for building a theme. I’m a great admirer of it and thoroughly endorse using it. However, it includes certain assumptions that didn’t chime with my spartan goal of making the smallest possible WordPress site.

Such as, you ask?

Nav? No. Sidebar? Get rid of it. Classes? Not in my socialist utopia.

Given the constraints I had set, anything making it to the DOM had to have a very good reason to be there. With this being an experiment, I took the somewhat radical approach of relegating the navigation to its own page. This is wonderfully liberating and means I didn’t have to go through the almost always disappointing dance of wondering how I would make it look presentable, hide it for the many users who won’t care, make sure it’s robust enough to be infinitely long with never-ending dropdowns, etc.

This means less HTML, less CSS, and definitely no JavaScript! Win, win, win.

As for the sidebar? Well I’ve always had an aversion to sidebars, so that was an easy thing to remove. Susty has no widget area. I’m sure it’ll get over it.

Is there more fat we can trim? Well, if we’re going to have hardly any HTML, and we want minimal CSS, do we really need all those classes? I wanted to try my hand at writing CSS in the way it was intended to be used, instead of bowing to the class-ititis and div-ititis that pervade the industry.

You might not need web fonts

Alongside images, video and JavaScript, the other item that has become a significant factor in bloated websites is web fonts. Given that it’s now a Silicon Valley fashion for every startup to commission its own typeface as a first order of business, it seems as though every website you visit incurs downloading a bunch of font files. It may not seem so bad to tack on a hundred kilobytes for some nice type, but when you multiply this by the many different people visiting your website across different devices and browsers, fonts can easily account for hundreds of megabytes of data transfer — if not gigabytes/terabytes/petabytes for higher traffic websites.
Custom web fonts are also a potential antipattern for our users, for whom:

  1. Page loads are slowed down as they see either a flash of unstyled text or, potentially even worse, no text while the font loads.
  2. By the time the font has loaded, they don’t notice or care.

If you do have to use custom fonts or are in combat with the flash of un-styled text, font-display is an new property designed to instruct the browser how to handle font downloads. This post goes into it even more.

Almost every device these days has a half-decent set of fonts installed, so why not compose a stack of potential fonts you’d like to see, ending with either “serif “ or “sans-serif.” Or embrace those default fonts altogether with a system font stack.

I wanted Susty to have a bit of a Swiss Style aesthetic, so my font stack ranges from the perfectly proportioned Helvetica (which all Apple devices have by default) to sans-serif, by way of Arial, Frutiger and Nimbus Sans L.

As an Ubuntu user, I see Arial, which is perfectly pleasant. On my Android devices I see the default sans-serif font (Droid Sans I believe), which actually works rather well on mobile — you’d almost think that’s what it was designed for!

What else? Standard stuff. Few or no images and SVG where possible

Beyond this, it’s really just the standard. The homepage of sustywp.com has no images and just one SVG which is loaded inline rather than by an HTTP request. The CSS is minified. Everything gets Gzipped. The server is tuned with NGINX and Fast-CGI cache to serve content from memory.

Bonus SPA-like features without the work or code

When I was boring my girlfriend, Daisy, with my plans, I asked her how she felt conceptually about a website not having a navigation, and it instead being on its own page, found via a „menu” button. She thought it sounded ok. So, when I came to show it to her, I watched eagerly as she clicked the menu link. Her response was that she didn’t really think about clicking to see the menu, and the menu appearing, as changing pages. This confirmed one of my fears that my previous obsession with eliminating page loads when building Single Page Apps (SPAs) is something that only really bothers web developer-y types. Most people don’t really notice it or think about it. So, if you make your website lightning fast, the page loads themselves are almost imperceptible anyway.

With that being the case, I figured why not just pretend it was a menu overlay? So, I added a cross dismiss button and a tiny bit of JavaScript to take you from the menu back to the previous page if you click it. (I did initially implement this in PHP using the $_SERVER superglobal and HTTP_REFERER, but this breaks when using something like FastCGI cache to serve pages (i.e. those pages there is no $_SERVER superglobal.)

There’s still more to come

We all know that things can always be better. Here are a few of the things I’m working on to improve Susty:

  • Finish reading Jeremy Keith’s book Going Offline so I can implement a Service Worker and make Susty even more performant.
  • Look to see how I can implement Gutenberg. It’s going to add a bunch of kilobytes and that makes me sad! 😉
  • Currently, sustywp.com is hosted in one data center in London, and served globally from that location. This means that someone in Wellington, New Zealand is not going to get the full experience! I have a longer-term plan of establishing my own little CDN of edge servers (each one hosted by a 100% renewable energy powered host in each location that I can find one) just running NGINX and serving cached versions of the site. This is a simplified way of how we do things on WordPress.com VIP.

In conclusion

Susty is an example of taking sustainable design techniques to an extreme. I’m not suggesting that we should all start building websites with this exact method. But I do think sustainability should be a much higher priority in the web design industry. It’s good to think about saving any kilobytes we can, and to think in terms of kilobytes rather than megabytes. If you do want to use a JavaScript interface library, why not try out Choo.js, which has React-like features and comes in at just 4KB. Remember, NASA managed to put a man on the moon with about 50KB of data storage at their disposal.

The best thing about all this is that efficient websites means faster websites, which means:

  • Happier users
  • Better search engine placement
  • Happier servers

The post Delivering WordPress in 7KB appeared first on CSS-Tricks.

Writing Good Support Requests

Post pobrano z: Writing Good Support Requests

My take on trying to be helpful to a support staff.

One bit is just as relevant for learning development:

Writing out a ticket will help you figure out the problem.

Sometimes when you have to take a second to collect your thoughts and explain something, the problem will become clear and maybe even the solution. Oftentimes, a bug is a bug and just needs to be fixed — but sometimes your support ticket might actually be something you can sort out for yourself and writing things out might be the first step toward that.

You know what they say, the best way to learn something is to teach it.

Just replace „ticket” with „forum topic” or whatever, on something like Spectrum.

Direct Link to ArticlePermalink

The post Writing Good Support Requests appeared first on CSS-Tricks.

One-Offs

Post pobrano z: One-Offs

There is this sentiment that you don’t design the homepage of a site first. For most sites, it’s an anomaly. It’s unlike any other page and not something to base the patterns you use for the rest of the site or help inform other pages.

You might call it a one-off.1

One-offs are OK! A world without one-offs is very boring. But a site chock-full of one-offs leads to familiar problems: inconsistency and non-reusable CSS that leads to bloating and maintainers that don’t really know what’s used and what isn’t.

What are we to do?

Brad Frost thought about this recently with his article Where to put one-off components?:

It’s quite likely that individual applications contain components that fit the very real needs of a specific application (think calculators, holiday-season parallax hero units, context-specific interactive maps, and so on), but may not be able to be immediately (or ever) abstracted into a generic, reusable component that’s included in the design system.

And Ethan Marcotte:

Here’s an example: let’s say you’ve designed a splashy-looking hero image. (Nice work, by the way. It looks very splashy.) Let’s also say its scope is fairly limited: perhaps it’s being used on a small number of pages, or it’s tied to one specific section of your website. In other words, it’s generic enough to be a pattern, but it’s not a widely-used one.

As you might have guessed, this is a dangerous place for a pattern to be. If a pattern feels a little idiosyncratic, that should always prompt us to ask: should your team keep the pattern, or remove it?

Thing is, there’s no single, easy answer to that question. Every pattern is different, and each pattern’s value is variable. Maybe we’ll drop that pattern altogether; maybe we’ll combine it with another, similar pattern

Brad connected the idea of a one-off to Harry Robert’s shame.css concept:

The idea of shame.css is that you have a totally new stylesheet reserved just for your hacky code. The code you have to write to get the release out on time, but the code that makes you ashamed.

But maybe a CSS file like that doesn’t need to be reserved just for „hacks” or shamefully quickly-written fixes (hey, it’s better than inline styles), but also for one-offs.

From a developer-in-charge-of-styling perspective, it’s interesting to consider how different styling methologies come into play here. For those travelling the atomic CSS road, in a sense, everything is a one-off. You might still have a pattern that is visually or behaviorly a one-off because of how you’ve built it, but not because it uses a different set of CSS. Callum Jefferies on his experience with atomic CSS:

I no longer had to think about how to organise my CSS. I didn’t have to think about what to name my 'components’, where to draw the line between one component and another, what should live where, and crucially, how to refactor things when new requirements came in.

So, too, with the 36 flavors of CSS-in-JS. When your styles are attached to your components, all components are one-offs. Stop using that component, stop using those styles.


1 Apparently one-off is a fairly new expression:

As William Safire observed in a 2007 On Language column, one-off meaning „something unique” is a British expression that has been creeping into American speech and writing in recent years. And as with other Briticisms that impinge on these shores (gone missing comes to mind), the idiomatic origins of one-off are mostly lost on American ears.

The post One-Offs appeared first on CSS-Tricks.

CSS Grid in IE: CSS Grid and the New Autoprefixer

Post pobrano z: CSS Grid in IE: CSS Grid and the New Autoprefixer

In Part 1 of this series, I debunked a few misconceptions that many people have around the Internet Explorer (IE) implementation of CSS grid. This article builds on that knowledge. It would be best to go back and read that article first if you haven’t already.

Today I’m going to be tackling the biggest misconception of all: that utilizing the IE implementation of CSS grid is extremely difficult. You can easily use CSS grid in IE right now without having to give it any sort of crappy fallback layout. It really isn’t that hard.

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps (Coming Soon!)

Giving IE a crappy fallback layout is a bit of a tough sell to clients. It is especially tough if this is for an intranet where 90% of the users are using IE. If you want IE compatibility, first you need to resign to the fact that you can’t use all of the fancy bells and whistles that can be found in the modern CSS grid spec. Don’t let this get you down though, you would be amazed by how much IE11 can handle, especially if it has some help from Autoprefixer.

Before I get too far into this, you need to know that this isn’t a general „how to use CSS grid” article. This article is for those that understand CSS grid, but are either too afraid or not allowed to use it, thanks to IE.

I’ll be assuming that you already have a good understanding of how to use CSS grid in modern browsers for this article. If you aren’t sure about how to use CSS grid yet, go watch Rachel Andrew’s excellent CSS grid video tutorial series. After that, go play some levels of the browser game Grid Garden to get some hands-on CSS grid experience. Once you understand the basics of how to use CSS grid in modern browsers, come back here and learn how to use it in a way that produces identical results in IE10 and 11.

Setting up Autoprefixer

Before you do anything else, you will want to get Autoprefixer up and running. Autoprefixer is a tool used for automatically adding browser-specific CSS prefixes to your CSS so that you don’t have to. It’s a bit like Babel but for CSS. (We have a great overview by the creator of Autoprefixer here on CSS Tricks.)

If you have never used Autoprefixer (or any build tool) before, then first install Node on your computer then follow this guide on how to get a basic workflow up and running. The bit in the guide specifically about Autoprefixer is found here. (I recommend the Gulp setup over Grunt if you aren’t sure which to go with.)

If you are already using Autoprefixer in your projects, make sure to update it to the latest version using this command:

npm i autoprefixer@latest -D

Some features used in the latest version of Autoprefixer are not supported in PostCSS version 5. This means that you may also need to update your version of PostCSS to at least version 6. If using Gulp, that means updating gulp-postcss to at least v7.0.0. If using Grunt, you may need to update grunt-postcss to at least v0.9.0.

Once you have an environment up and running, you will need to set the Autoprefixer grid setting to true. Without that setting turned on, Autoprefixer will not be able to do any of the cool stuff that I’m about to show you.

The exact method for turning the grid setting on depends a lot on how you compile your code. If you were using the guide that I linked to earlier, you would have seen this snippet of code:

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

Add grid: true to the options to turn grid prefixing on:

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ grid: true, browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

By the way, the browser settings in the tutorial are pretty outdated and will be outputting far more prefixes than you actually need. Just going with ">1%" will mean that when a browser dies, Autoprefixer will automatically stop writing prefixes for that browser. It bases browser usage on global browser data retrieved from caniuse.com.

So, these are the Autoprefixer settings that you should end up using:

var processorsArray = [
  require('autoprefixer')({ grid: true, browsers: ['>1%'] })
];

Now onto the fun stuff! 😃

Autoprefixer has new super powers!

You may have read Rachel Andrew’s article „Should I try to use the IE implementation of CSS Grid Layout?” That article is all about CSS grid and understanding it’s support in IE10 and 11. It’s a great article and very useful for understanding IE’s limitations. Definitely still worth a read if you haven’t already checked it out. Note that it is extremely outdated in terms of its information on Autoprefixer though.

Autoprefixer has come a long way since Rachel wrote her IE11 CSS grid article and Autoprefixer now supports far more CSS grid translations. Take a look at this new, updated version of Rachel’s table based on Autoprefixer version 8.6.4. Note that items in bold represent a change in Autoprefixer support compared to Rachel’s article:

CSS Grid Property IE10 Implementation Autoprefixer? Notes
grid-template-columns -ms-grid-columns Yes
grid-template-rows -ms-grid-rows Yes
grid-template-areas NA Yes Autoprefixer uses this to understand what the grid looks like but does not add any extra properties.
grid-template NA Yes Shorthand for grid-template-columns, grid-template-rows, and grid-template-areas
grid-auto-columns NA No IE doesn’t support auto-placement
grid-auto-rows NA No IE doesn’t support auto-placement
grid-auto-flow NA No IE doesn’t support auto-placement
grid NA No See this GitHub issue as to why this isn’t supported
grid-row-start -ms-grid-row Yes1 Span syntax requires grid-row-end to be defined
grid-column-start -ms-grid-column Yes1 Span syntax requires grid-column-end to be defined
grid-row-end NA Yes1 grid-row-start must be defined
grid-column-end NA Yes1 grid-column-start must be defined
grid-row NA Yes1
grid-column NA Yes1
grid-area NA Yes2 Autoprefixer translates the grid area into column/row coordinates
grid-row-gap NA Yes3 Generates extra rows/columns in IE.
grid-column-gap NA Yes3 Generates extra rows/columns in IE.
grid-gap NA Yes3 Generates extra rows/columns in IE.
NA -ms-grid-column-span Yes Translated from grid-column-end and grid-area.
NA -ms-grid-row-span Yes Translated from grid-row-end and grid-area.
align-self -ms-grid-row-align Yes
justify-self -ms-grid-column-align Yes

Table disclaimers

I will cover these in far more detail later in the article:

  1. Autoprefixer cannot prefix negative integers.
  2. Each grid element must have unique area names.
  3. Autoprefixer only prefixes grid-gap if both grid-template-areas and grid-template-columns have been defined. It also cannot inherit grid-gap through media queries.

grid-template-areas is your new best friend

As you can see from the updated (and much more positive-looking) table, there are a lot of cool new features in Autoprefixer now. The most important of which is its support for grid-template-areas (and by extension grid-template). By supporting grid-template-areas, Autoprefixer now understands exactly what your grid looks like. This paved the way for Autoprefixer to also support (in a limited capacity) grid-gap.

Note that Autoprefixer still does not support the shortcut grid property. This was an intentional design decision that you can learn more about in this GitHub issue. The short story is that the grid property is not only a shortcut for the templating settings but also the auto-placement settings. Since IE can’t do auto-placement and the grid-template property can essentially do anything that the grid property can do (that IE can handle), it was decided that the grid property wasn’t worth supporting.

Back when Rachel wrote her article, this was the sort of grid code you would need to write in order to support IE:

/* IE-friendly source code 26 November 2016 */
/* Code needed to make Autoprefixer work properly */

.grid {
  display: grid;
  grid-template-columns: 1fr 10px 1fr;
  grid-template-rows: 100px 10px 100px;
}

.cell-A {
  grid-column: 1;
  grid-row: 1;
}

.cell-B {
  grid-column: 3;
  grid-row: 1;
}

.cell-C {
  grid-column: 1;
  grid-row: 3;
}

.cell-D {
  grid-column: 3;
  grid-row: 3;
}

Now, you can write code like this instead:

/* Today’s IE-friendly source code */
/* Autoprefixer can now make this code IE safe */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px /
    1fr  1fr;
}

.cell-A {
  grid-area: a;
}

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

Autoprefixer will take the above code and translate it into this much more IE-friendly code for you:

/* Autoprefixer’s IE-friendly translation */

.grid {
 display: -ms-grid;
 display: grid;
 grid-gap: 10px;
 -ms-grid-rows: 100px 10px 100px;
 -ms-grid-columns: 1fr 10px 1fr;
 grid-template:
   "a   b" 100px
   "c   d" 100px /
   1fr  1fr;
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

Best of all, you can then simply change the grid-template or grid-template-areas property with a media query and Autoprefixer will automatically update all of the grid cell coordinates for you:

/* Changing a grid-template with a media-query */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px){
  .grid {
    /* Autoprefixer 8.6.4 doesn't inherit grid gaps :( */
    grid-gap: 10px;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

.cell-A {
  grid-area: a;
}

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

.cell-E {
  grid-area: e;
}

.cell-F {
  grid-area: f;
}

The above gets translated into this IE-friendly code:

/* Autoprefixer’s IE-friendly media query translation */

.grid {
  display: -ms-grid;
  display: grid;
  grid-gap: 10px;
  -ms-grid-rows: 100px 10px 100px 10px 100px;
  -ms-grid-columns: 1fr 10px 1fr;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px) {
  .grid {
    /* Autoprefixer 8.6.4 doesn't inherit gaps :( */
    grid-gap: 10px;
    -ms-grid-rows: 100px 10px 100px;
    -ms-grid-columns: 1fr 10px 1fr 10px 1fr;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

.cell-E {
  -ms-grid-row: 5;
  -ms-grid-column: 1;
  grid-area: e;
}

.cell-F {
  -ms-grid-row: 5;
  -ms-grid-column: 3;
  grid-area: f;
}

@media (min-width: 600px) {
  .cell-A {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
  }
  
  .cell-B {
    -ms-grid-row: 1;
    -ms-grid-column: 3;
  }
  
  .cell-C {
    -ms-grid-row: 1;
    -ms-grid-column: 5;
  }
  
  .cell-D {
    -ms-grid-row: 3;
    -ms-grid-column: 1;
  }
  
  .cell-E {
    -ms-grid-row: 3;
    -ms-grid-column: 3;
  }
  
  .cell-F {
    -ms-grid-row: 3;
    -ms-grid-column: 5;
  }
}

The duplicate media query might look a bit ugly but I assure you that this is the best possible way that Autoprefixer can handle the media query translation. The new IE grid cell coordinates could not be placed into the same media query as the grid template definition. Doing so would lead to one of two possible outcomes. One outcome is that the default grid cell positions would override the altered positions stated in the media query. This would cause the media query to have no effect in IE. The other outcome would be for Autoprefixer to shift all of the styles inside the media query (yes, that includes all of the styles that you wrote yourself) to another location in the style sheet, potentially causing horrific CSS specificity issues. You can learn more about the thinking behind this decision in the now closed GitHub issue for it.

Autoprefixer still can’t save you from everything

Even Superman can’t always save everyone and Autoprefixer is no different. While Autoprefixer is able to cut down on a lot of the workload involved in making our grids IE-compatible, it can’t fix everything. It can only translate things that IE can understand. These are the many critical things that you need to be aware of if you don’t want to open the site up in IE one day and have it blow up in your face.

Grid Gap has limited support

As you may have seen in that last example, grid-gap isn’t currently able to be inherited through media queries. If you want to use grid-gap, you will need to duplicate the grid-gap setting across all of the media queries where you define a grid template for that grid. There is an issue open on GitHub about this. Go give it a thumbs up if you want Autoprefixer to support it. Hopefully the issue is fixed soon.

That isn’t the only problem around using grid-gap though. It is only supported by Autoprefixer when both grid-template-areas and grid-template-columns have been defined.

Autoprefixer adds grid-gap support by using grid-template-areas to understand what your grid looks like. It then takes your grid-template-columns and grid-template-rows definitions and injects the grid-gap value between each row and column, creating extra rows and columns in IE.

If you try to use grid-gap on its own without grid-template-areas, Autoprefixer has no way of knowing what cell belongs to what grid. Without that critical knowledge, it cannot safely inject the extra columns and rows that IE needs.

That explains grid-template-areas but why do we also need to define grid-template-columns? Shouldn’t something like this be just as easy for Autoprefixer to translate?

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-areas:
    "a  b  c"
    "d  e  f";
}

.cell-a {
  grid-area: a;
}

.cell-f {
  grid-area: f;
}

Rows and columns in CSS grid default to a value of auto so can’t Autoprefixer just add something like -ms-grid-columns: auto 20px auto 20px auto;? It does that for rows, so why can’t it do the same thing for columns?

Well my inquisitive friend, I explained in Part 1 that auto in IE acts a bit differently to auto in modern browsers. When columns are set to auto in IE, they will always shrink down to the value of max-content. Modern grid columns, on the other hand, will expand to 1fr if there are no other fr units being used in that grid template declaration. This discrepancy can cause a massive difference in appearance between the modern and the IE version of a grid. The Autoprefixer team felt that it was too dangerous to make assumptions about this, so they made grid-template-columns a mandatory setting in order for grid-gap to take effect.

So that explains why Autoprefixer doesn’t support grid-gap when grid-template-columns is missing. If auto behaves so differently in IE, then why does Autoprefixer support grid-gap without the user explicitly having to define grid-template-rows? Isn’t that just as bad?

Not really. When you set display: grid; on something, it’s width will grow to the full width of its container. Its height, on the other hand, typically shrinks to the height of its content. Of course this isn’t always the case. There are a number of reasons why a grid might be taller than its content. If the grid is also a flex item and the flex container is taller than the grid, then that would be one reason why the grid might be taller than its content. In general though, if there are no other forces involved, then a grid container will always be the same height as its content.

Since the height of a typical grid is the same height as its content, in most cases, auto in both IE and modern browsers will behave identically to one another. It will only differ in functionality if the height of the grid exceeds the height of the content inside of it. For the best balance between user convenience and browser consistency, the Autoprefixer team made a choice. They decided that supporting a missing grid-template-rows property but not a missing grid-template-columns property was the best way to handle grid-gap support.

No auto-placement! No auto-placement! No auto-placement!

I really can’t say this enough. The most important thing to remember when using CSS grid in IE is that everything must be placed manually. The instant you start thinking about using auto-placement is the instant your site blows up in IE. I have a method for dealing with grids that have an unknown number of cells in them. I’m covering that in Part 3 of this series. The main thing to know right now is that if you want to use CSS grid in an IE-friendly way, you should only ever use it if there are a known number of cells for a known number of rows and columns.

It’s this lack of auto-placement in IE that makes having access to grid areas through Autoprefixer such a blessing. Instead of having to calculate all of the coordinates manually, you can instead name each cell and then let Autoprefixer do the math for you. When using media queries, you only need to redefine the grid template and autoprefixer will recalculate all of the coordinates for you. You rarely have to do any column or row counting. It’s great!

Area names must be unique

The ability to use grid-template-areas is one of Autoprefixer’s greatest strengths, though it has its limits. Autoprefixer does not have any access to the DOM. Due to this, Autoprefixer is entirely dependent on using the area name for understanding where each cell needs to be placed in the grid. This can cause clashes if you use the same area name twice in the same stylesheet.

Here is a small example. Early in the stylesheet, Grid Alpha has grid-template-areas: "delta echo". Later in the stylesheet, Grid Beta has grid-template-areas: "echo delta". We say that our grid cell belongs to area echo… so does it go in column 1 or 2?

.grid-alpha {
  grid-template-areas: "delta  echo";
}

.grid-beta {
  grid-template-areas: "echo  delta";
}

.grid-cell {
  /* What column does .grid-cell go in? */
  -ms-grid-column: ???;
  grid-area: echo;
}

Modern browsers know exactly what column to place the grid cell in because they have access to the DOM. If the cell is placed inside Grid Alpha, it will go in the first column. If it is placed in Grid Beta it will go in the second column. Autoprefixer can only read your CSS. It has no idea if the grid cell is placed in Grid Alpha or Grid Beta. All it knows is that the grid cell needs to be placed in the „echo” area. Autoprefixer resolves this conundrum by going with whichever one came last in the stylesheet. In this case, Autoprefixer will honor Grid Beta’s "echo delta" areas definition since it occurs last. If you placed the grid cell inside Grid Alpha, it would look great in modern browsers but it would be placed in the wrong column in IE.

This also means that you can’t really use the strategy of giving a component a single designated area name that is repeatedly referenced. Referencing that area name in more than one grid-template-areas property will break IE for sure. Every single area name across every single grid in your style sheet needs to be unique or Autoprefixer will freak the heck out.

Autoprefixer currently does not warn you when you have used a duplicate area name in your stylesheet. If you would like to start seeing warnings for duplicate area names, there is an issue open on GitHub that you can add your support to. In the meantime, the easiest way to ensure that each area name is unique is probably adopting a BEM style approach to naming the areas.

.grid-alpha {
  grid-template-areas: "grid-alpha__delta  grid-alpha__echo";
}

.grid-beta {
  grid-template-areas: "grid-beta__echo  grid-beta__delta";
}

.grid-cell {
  /* No more conflict :) */
  -ms-grid-column: 2;
  grid-area: grid-alpha__echo;
}

This can be pretty verbose if there are lots of columns and rows. You might want to shorten it down to an abbreviation instead. Of course, the less verbose your area names, the more chance there is of a conflict.

.grid-alpha {
  grid-template-areas: "ga_delta  ga_echo";
}

.grid-beta {
  grid-template-areas: "gb_echo  gb_delta";
}

.grid-cell {
  -ms-grid-column: 2;
  arid-area: ga_echo;
}

There is one major exception. Grid areas in media queries are allowed to be duplicates of other areas as long as the area names defined in the media query are targeted at the same element. Without this exception, it would be impossible to change the grid areas based on screen size. The main thing to remember is that each grid has to have its own set of unique area names that must not be shared with any other grids.

@media (min-width: 600px) {
  .grid-one {
    grid-template-areas:
      "alpha bravo"
      "alpha charlie";
   }
}

@media (min-width: 900px) {
  .grid-one {
    /* This is fine */
    /* It is targeting the same element */
    grid-template-areas:
      "alpha bravo charlie";
  }
}

@media (min-width: 900px) {
  /* NOT FINE! */
  /* The "alpha" area is being reused on a different element! */
  .grid-two {
    grid-template-areas:
      "alpha delta";
  }
}

Autoprefixer has limited column and row spanning support

There are only two properties in IE’s implementation of CSS grid that will help you span multiple columns. The main one being -ms-grid-column/row-span which tells IE how many columns/rows to span. The other being -ms-grid-column/row which tells IE where to start counting from.

.grid-cell {
  -ms-grid-column-span: 2; /* number of cells to span */
  -ms-grid-column: 1; /* starting cell */
}

In modern browsers, you have access to far more options.

Autoprefixer friendly

Out of the modern ways to span multiple cells, Autoprefixer fully supports the following. Feel free to use any of these methods as much as you like:

Specify a starting line and the number of lines to span (similar to IE):

.grid-cell {
  grid-column: 1 / span 2;
}

Specify an end line, then span backwards:

.grid-cell {
  grid-column: span 2 / 3;
}

Specify a starting line and an end line directly:

.grid-cell {
  grid-column: 1 / 3;
}

Specify only a number of cells to span using grid-column/row-end. Remember that IE can’t do auto-placement though. A starting line will still need to be specified elsewhere in the style sheet:

.grid-cell {
  /* Make sure you specify a starting line elsewhere */
  grid-column-end: span 2;
}

Specify only a starting line:

.grid-cell {
  /* The short way */
  grid-column: 1;

  /* The more verbose way */
  grid-column-start: 1;
}
Autoprefixer unfriendly. Here be dragons!

Now this is where Autoprefixer reaches its limit. The following methods are supported in modern browsers but are not supported by Autoprefixer. This is mainly due to Autoprefixer having no idea what grid the grid cell belongs to since it can only base its decisions on what is in the stylesheet.

Specify a starting line and how many lines from the end of the explicit grid to span:

.grid-cell {
  grid-column: 1 / -1;
}

Specify both the start and end line from the end of the explicit grid:

.grid-cell {
  grid-column: -3 / -1;
}

Specify only how many lines to span using the shorthand syntax (issue in GitHub):

.grid-cell {
  grid-column: span 2;
}

Specify only a backwards span (IE can’t span backwards):

.grid-cell {
  grid-column-start: span 2;
}

Specify only an end line (IE doesn’t understand end and Autoprefixer doesn’t know where the start is):

.grid-cell {
  grid-column-end: 3;
}

So, basically avoid counting backwards from the end of the grid and you’ll be fine. 😊

Avoid using line names for now

One of the cool features of modern grids is giving grid templates line names. Instead of using numbers to reference a line, you can give the line a name and reference that instead. Since Autoprefixer supports grid areas, you would think that they would also support line names. Unfortunately, that isn’t the case. As of version 8.6.4, Autoprefixer does not support line names (at the time of writing). Don’t worry though! It’s not that it is impossible to support (at least not entirely), it just hasn’t been a high priority for them. If you love using line names in your grids then let them know about it in the GitHub issue for it. Post your use cases and it will surely increase the priority of the feature. In the meantime, see if you can use grid areas instead for now.

Keep in mind that, if it is going to be implemented, then every line name across your stylesheet would need to be unique. Like with grid areas, Autoprefixer wouldn’t know what line name belongs to what grid. The only way it can tell is if every line name in the stylesheet is unique (excluding media queries).

You still need to test!

IE will behave itself most of the time as long as you follow all of the rules we’ve covered so far. That said, IE can still be a bit unpredictable. Just recently, I made a grid item a vertical flowing flex container and encountered an odd bug in IE11. The column width was set to minmax(min-content, 350px) but IE seemed to treat min-content like max-content in this circumstance. This completely broke the layout. Changing it to minmax(0, 350px) fixed the issue. Just goes to show that IE’s grid implementation isn’t quite perfect.

There are also times when you might accidentally forget to explicitly place grid cells. We build our grids in modern browsers because they have the nice grid development tools (especially Firefox). Modern browsers have auto-placement, though. This means that you might be halfway through building your grid then get called away for a moment. When you return to your desk, you see the layout looking beautiful in your browser, but you completely forget that you haven’t explicitly placed any grid cells yet. You move onto the next thing, blissfully unaware that you have left IE in a completely broken state.

Neither of those issues will reveal themselves until you test your site in IE11. Any time that you get a grid looking good in a modern browser, open it up in IE and double-check that it still looks the way you expect it to.

Autoprefixer control comments

Despite Autoprefixer’s best efforts, there are still some rare occasions when it seems like Autoprefixer is hindering you more than it is helping you. If you ever find yourself in a situation where it would be easier to not have Autoprefixer translating your code, you can turn Autoprefixer off using something called a „control comment.”

autoprefixer: off

This control comment will turn off Autoprefixer translations for the entire CSS block. It will not prefix any styles before or after the point where the comment is made.

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: -ms-grid;
  display: grid;
}

autoprefixer: ignore next

If you are after more of a scalpel than a sledge hammer, the /* autoprefixer: ignore next */ control comment is more for you. „Ignore next” will skip the next CSS declaration rather than ignoring the entire CSS block.

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: -ms-grid;
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

Pre-processor comments

If you are using Sass (or another CSS pre-processor) in your project, do not use the double slash (//) method for writing these comments. Sass will strip those comments out before Autoprefixer has a chance to translate the code.

/* Input SCSS */

.normal-behavior {
  display: grid;
}

.failed-off-behavior {
  // autoprefixer: off
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
}

.failed-off-behavior {
  display: -ms-grid;
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}

Let’s recap!

So, after all that, here is the list of all the things you need to remember to be an IE11 CSS grid master:

  • Use the latest version of Autoprefixer (npm i autoprefixer@latest -D).
  • Turn on the Autoprefixer grid setting.
  • Do not attempt to use auto-placement, every cell must be placed manually.
  • Use grid-template-areas as your primary method for placing grid cells into position.
  • Use grid-template (not grid) as a shortcut.
  • Don’t use duplicate area names unless they are inside a media query targeting the same element. Also, give this GitHub issue your support if you would like Autoprefixer to warn you when you have used a duplicate area name.
  • You can use grid-gap as long as you define both grid-template-areas and grid-template-columns.
  • grid-gap is currently not inherited through media queries. Go give this GitHub issue a thumbs up if you want to write less grid-gap code.
  • When spanning multiple columns and rows, avoid counting backwards from the end of the grid. Autoprefixer doesn’t understand your grids well enough to supports this.
  • Avoid using line names for now. Give this GitHub issue a thumbs up if you want to start using them.
  • Use control comments /* autoprefixer: off */ and /* autoprefixer: ignore next */ to prevent Autoprefixer from translating certain parts of your style-sheet that are causing problems.
  • Don’t forget to test!

…and from Part 1:

  • IE does have an implicit grid.
  • IE supports repeat functionality.
  • minmax(), min-content and max-content are all natively supported.
  • fit-content() isn’t natively supported but you can work around this with auto and max-width settings.
  • IE auto is not equal to auto in modern browsers.

If you have any questions, or if this really helped you out, let me know in the comments! I’m also @Daniel_Tonon on Twitter. 😁

Up next…

In Part 3, I will be covering how to make a fully responsive flexbox-based grid in IE11. This flexbox technique even replicates grid-gap functionality!

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps (Coming Soon!)

The post CSS Grid in IE: CSS Grid and the New Autoprefixer appeared first on CSS-Tricks.

Clearfix: A Lesson in Web Development Evolution

Post pobrano z: Clearfix: A Lesson in Web Development Evolution

The web community has, for the most part, been a spectacularly open place. As such, a lot of the best development techniques happen right out in the open, on blogs and in forums, evolving as they’re passed around and improved. I thought it might be fun (and fascinating) to actually follow this creative exchange all the way through. To take a look at a popular CSS trick, the clearfix, and find out exactly how a web design technique comes to be.

The clearfix, for those unaware, is a CSS hack that solves a persistent bug that occurs when two floated elements are stacked next to each other. When elements are aligned this way, the parent container ends up with a height of 0, and it can easily wreak havoc on a layout. All you might be trying to do is position a sidebar to the left of your main content block, but the result would be two elements that overlap and collapse on each other. To complicate things further, the bug is inconsistent across browsers. The clearfix was invented to solve all that.

An early illustration of the issue from Position is Everything

But to understand the clearfix, you have to go back even further, to the 2004 and a particular technique called the Holly hack.

2004: The Holly Hack and the origin of Clearfix

The Holly hack is named for its creator, Holly Begevin, a developer and blogger at CommunityMX. The Holly hack combines two different CSS techniques that worked in the days of Netscape Navigator and Internet Explorer (IE) 4 to solve some layout issues. Begevin noticed that if you apply a height of just 1% to each of the floated elements in the above scenario, the problem would actually fix itself (and only because it activated an entirely different bug) in Internet Explorer for Windows.

Unfortunately, the 1% trick didn’t work on a Mac. For that, Begevin added a conditional comment which used a backslash inside of her CSS, which strangely enough, blocked individual CSS rules from IE for Mac in the old days. The result was a CSS trick that looked like this:

/* Hides from IE5-mac \*/
* html .buggybox {height: 1%;}
/* End hide from IE5-mac */

Odd, I know, but it only gets more complicated.

That same year, in May, there were a few more browsers to deal with, and not all of them could be patched with one line of CSS. Tony Aslett posted a new thread to his message board, CSS Creator, proposing a new approach. He called the trick a clearfix because it centered around clearing the floated elements to fix the issue.

Aslett’s approach took advantage of what were, at the time, still very new CSS pseudo-selectors (specifically :after) to automatically clear out two floated elements. There was one pretty massive drawback in Aslett’s first version of the clearfix. Having never heard of the Holly Hack, Aslett’s code required a bit of JavaScript to fix issues that were specifically popping up on IE for Mac. In those days, JavaScript was a relatively untested technology, and relying on it in such a fundamental way was less than ideal.

Thankfully, the web is a place of iteration, and one message board user pointed Aslett in the direction of the aforementioned Holly Hack. By sprinkling in Begevin’s conditional comment, Aslett was able to make his code work in just about every browser with no JavaScript at all.

.floatcontainer:after {
  content: "."; 
  display: block; 
  height: 0; 
  clear: both; 
  visibility: hidden;
}

/* Mark Hadley's fix for IE Mac */     
.floatcontainer {
  display: inline-block;
}

/* Hides from IE Mac \*/
* html .floatcontainer {height: 1%;}
.floatcontainer{display:block;}
/* End Hack */

If you want to pick apart an important slice of web history and innovation, the discussion that followed Aslett’s post about clearfix is a great place to start. One by one, people began to experiment with the new technique, testing it in obscure browsers and devices. When they were done, they’d post their results to the message thread, sometimes alongside a helpful tweak.

For example, the user zulaica pointed out that in Mozilla browsers, the bottom border of floated elements had to be explicitly defined. User pepejeria noticed that you could leave out the dot from content, and user co2 tested the clearfix in the very first version of Apple’s Safari browser. Each time, Aslett would update his code a bit until, after more than a few rapid iterations, the clearfix was ready and, thanks to the community, pretty darn bulletproof.

2006: Clearfix gets an update

But browsers kept on advancing. Some of the more quirky bits of the clearfix code worked because of bugs that were built into older browsers. As browsers patched those bugs, in brand new versions, the clearfix stopped working. When IE 7 came out at the end of 2006, a few adjustments to the technique were needed to make it work.

Fortunately, John “Big John” Gallant was maintaining a page on his blog Position is Everything with an up to date version of the clearfix. After getting some feedback from his readers, Gallant updated his blog to reflect a few new fixes for IE 7 using a new kind of conditional comment that would work inside of Internet Explorer.

<style type="text/css">

  .clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }

</style><!-- main stylesheet ends, CC with new stylesheet below... -->

<!--[if IE]>
<style type="text/css">
  .clearfix {
    zoom: 1;     /* triggers hasLayout */
  }  /* Only IE can see inside the conditional comment
    and read this CSS rule. Don't ever use a normal HTML
    comment inside the CC or it will close prematurely. */
</style>
<![endif]-->

And once again, users took to their own browsers to test out the latest code to ensure it worked everywhere. And once again, for a time, it did.

2010: Clearfix Reloaded

In fact, this iteration of the clearfix would last until about 2010, when the team at the Yahoo! User Interface Library (YUI) noticed a few issues with the clearfix. The Holly Hack, for instance, was now long gone (IE 5 was but a distance memory), and after switching the box model, margins were handled a bit differently by modern browsers.

But the folks at YUI still needed to line up one element next to another. In fact, the need had only increased, as designers experimented with more advanced grid layouts. In 2010, there were very little options for grid layout, so clearfix had to work. They eventually came up with a few additional tweaks to the CSS ruleset, most notably by taking of advantage of both available pseudo-selectors (:before and :after), to clear out any margins. They posted their new take to their own blog and called it “clearfix reloaded.”

.clearfix:before,
.clearfix:after {
  content: ".";    
  display: block;    
  height: 0;    
  overflow: hidden;        
}
.clearfix:after { clear: both; }
.clearfix { zoom: 1 ;} /* IE < 8 */

2011: The Micro Clearfix

But even when it was published in 2010, clearfix reloaded brought with it some unnecessary baggage from older browsers. The height equals 0 trick wasn’t really a requirement anymore, and in fact, the trick was a lot more reliable when display: table was used instead. People began swapping various variations on the technique on Twitter and on blogs. About a year after the release of clearfix reloaded, developer Nicolas Gallagher compiled these variations into a much more compact version of the hack, which he appropriately labeled the micro clearfix.

After years of back and forth and slight adjustments, the clear fix now required just four CSS rules:

/*
 * For modern browsers
 * 1. The space content is one way to avoid an Opera bug when the
 *  contenteditable attribute is included anywhere else in the document.
 *  Otherwise it causes space to appear at the top and bottom of elements
 *  that are clearfixed.
 * 2. The use of `table` rather than `block` is only necessary if using
 * `:before` to contain the top-margins of child elements.
 */
.cf:before,
.cf:after {
  content: " "; /* 1 */
  display: table; /* 2 */
}

.cf:after {
  clear: both;
}

/*
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
  zoom: 1;
}

The End of Clearfix?

These days, almost 15 years after it was first proposed, the clearfix is losing a bit of relevance. CSS Grid and Flexbox are filling in the gaps for advanced layout on the web. In January of 2017, Rachel Andrew wrote an article for her blog titled „The end of the clearfix hack?” In it, she describes a way to replace the clearfix hack with a single line of code using a new display mode rule known as flow-root.

.container {
  display: flow-root;
}

We are approaching the day when clearfix will no longer be necessary at all.

Even without flow-root, there’s lots of ways to make a grid these days. If you were just starting out on the web, there’d be little reason to even learn about it. That’s a good thing! From the beginning it was always meant as a workaround to make the best of what was available. The irony being that without the dedication and experimentation of the developers who hacked away on the clearfix for so many years, we wouldn’t have the tools today to never have to rely on it again.

Enjoy learning about web history with stories just like this? Jay Hoffmann has a weekly newsletter called The History of the Web you can sign up for here.

The post Clearfix: A Lesson in Web Development Evolution appeared first on CSS-Tricks.

Vue + TypeScript: A Match Made in Your Code Editor

Post pobrano z: Vue + TypeScript: A Match Made in Your Code Editor

Vue is so hot right now and I’ve been thinking of doing a serious project with it since quite a while, so when the opportunity popped up, I hopped in. But there was a little problem — one of the requirements of the project was to write it in TypeScript. At first, I was super stressed about how I was going to ever get started on this combo, but vue-cli made it so easy.

I’d be lying if I said this ride was super smooth. There were frustrations, hours of staring at the screen and some fistbumps with my table but after working with Vue + TypeScript for over a month now, I can say it was worth it — and if I had to code another app with Vue, I wouldn’t do it without TypeScript.

Prerequisites

This article is about pairing Vue and TypeScript and assumes some basic knowledge of both. If you haven’t had a chance to play with them yet and are curious, Vue has a great guide, and the TypeScript docs are a great place to start.

We need to have vue-cli installed globally, so we can quickly spin up Vue project. Install vue-cli by running the following command in your terminal:

npm install -g @vue/cli

Once we have that installed, we’re good to go. If you don’t have TypeScript installed, we don’t need to do that beforehand, as vue-cli takes care of that when you start a new project and choose TypeScript there.

Getting Started

Now that we have vue-cli installed, all we need to do to get a project with Vue + TypeScript started is to run vue create. While creating a new project, choose TypeScript and we’re good to go.

vue create <app-name>

Here’s the result once our project spins up:

vue-cli also provides us the ability to choose Babel along with TypeScript for polyfills, CSS preprocessors, linter, unit testing libraries (I picked Jest, go Jest!) along with other config. You can even save your choices in a preset, to use it later, for another project.

Here’s a rundown of the handy questions you’ll get asked to configure the project:

One thing I’d like to mention is that vue-cli 3.0 comes with a user interface which makes it even more easy to create a new project. Run vue ui in terminal and vue-cli opens a UI where you can set up a new project.

What’s in the Box

After vue-cli is done, we get a nice directory structure of our app with all the setup already done.

  • tsconfig.json: This is all set up and we can edit it to suit our requirements.
  • shims-vue.d.ts: These shims are already set up to help TypeScript understand .vue files (Single File Components) when they are imported.
  • vue-property-decorator: If you choose to use class-style components, vue-cli adds this plugin so we can use all sorts of decorators. This comes quite handy and make the code more readable.
  • Class components: If you choose to use them, vue-cli sets the stage for you. Bear in mind that you would still need to register router hooks so class components can resolve them.

Sass Setup

One thing that I needed to set up and I wish was included out of the box was shared Sass partials. To avoid importing my Sass variables and mixins in every component, I had to load them in vue.config.js. shared.scss is the file exporting all variables and mixins that are used within the app.

Here’s where I landed with my Sass configuration:

chainWebpack: (config) => {
   config
     .module
     .rule('vue')
     .uses
     .get('vue-loader')
     .tap(({ loaders, loaders: { scss }, ...options }) => ({
       ...options,
       loaders: {
         ...loaders,
         scss: [
           ...scss,
           {
             loader: 'sass-resources-loader',
             options: {
               resources: [
                 './src/styles/shared.scss',
               ],
             },
           },
         ],
       },
     }));

Vue Property Decorator

The vue-property-decorator package exposes Vue properties and makes them available to use as decorators. In my application, I ended up using only @Component, @Prop, @Watch but there are others such as @Emit, @Inject and @Model, that make your code much more verbose when used extensively.

Vuex

Vuex has typings…nuff said! Vuex supports TypeScript to boot and, at first, I didn’t even know it. I started to look for proper ways to combine Vuex with TypeScript and stumbled upon Alex Jover Morales’ egghead.io course on Vue.js State Management with Vuex and TypeScript. It helped me understand the correct way of managing Vuex state when using TypeScript.

For example:

// actions.ts
import { ActionTree } from 'vuex';
import { RootState, ModuleState } from '@/types';


const actions: ActionTree<ModuleState, RootState> = {
  // all your actions go here
};

Vuex-class

This is yet another thing that I didn’t know existed when I first started but know wish I had found it sooner. I was creating getters for almost everything, but that didn’t feel right. I started looking for better ways to do this and found an interesting article by Francesco Vitullo which cleared up a few things for me. That’s where I found out about vuex-class which provides decorators for all vuex mappers.

So, now instead of writing a new getter for simply accessing a property in state, I could do this:

import {
  State,
} from 'vuex-class'

@Component
export class MyComp extends Vue {
  @State(state => state.bar) stateBar
}

Development Experience With VS Code

With TypeScript, the coding experience on VS Code is so much better. There is no going back and forth to check what mutation types I declared in mutation-types.ts because VS Code can recognize them and suggest correct ones as I type.

The same goes for modifying state in mutations — with TypeScript, the editor knew what my state structure looks like and suggests correct properties.

If you’re using VS Code, I strongly recommend using the Vetur plugin because it provides Vue tooling and comes with other bells and whistles like syntax highlighting (this works great with Vue single file components) and linting right out of the box.

Final Thoughts

Just like everything else in the JavaScript ecosystem, Vue + TypeScript still has a long way to go. For example, I could not use vuelidate because it doesn’t have typings. But thankfully vee-validate provided a workaround, so I didn’t have to go down the difficult road of writing those myself.

In conclusion, I found the development experience to be much smoother and VS Code is a totally different beast when you work with TypeScript. I don’t really need to sing the praises of Vue — it is very easy to pick up and start building and saves days trying to wrap your head around the inner workings of a framework.

The post Vue + TypeScript: A Match Made in Your Code Editor appeared first on CSS-Tricks.

Better rendering for variable fonts

Post pobrano z: Better rendering for variable fonts

I was messing around with a variable font the other day and noticed this weird rendering issue in the latest version of Chrome where certain parts of letterforms were clipping into each other in a really weird way. Thankfully, though, Stephen Nixon has come to the rescue with a temporary hack to fix the issue which using a text-shadow on the text that’s using the variable font:

.variable-font {
  text-shadow: 0 0 0 #000; /* text color goes last here */
} 

Once you do that, you shouldn’t be able to see those weird clip marks in the letterforms anymore. Yeah, it feels pretty hacky but I’m sure this rendering bug will be fixed relatively soon. It doesn’t look like it affects other browsers, as far as I can tell.

Direct Link to ArticlePermalink

The post Better rendering for variable fonts appeared first on CSS-Tricks.

Handling Errors with Error Boundary

Post pobrano z: Handling Errors with Error Boundary

Thinking and building in React involves approaching application design in chunks, or components. Each part of your application that performs an action can and should be treated as a component. In fact, React is component-based and, as Tomas Eglinkas recently wrote, we should leverage that concept and err on the side of splitting any large chunking into smaller components.

Splitting inevitably introduces component hierarchies, which are good because they bloated components and architecture. However, things can begin to get complicated when an error occurs in a child component. What happens when the whole application crashes?! Seriously, React, why do the parent and sibling components have to pay for the sins of another component? Why?

Error Boundaries

React 16 came with a lot of goodies, one of which is error boundaries. Let’s consult the documentation and break down what it says about this gem because we can use it to spot errors where they occur and resolve them faster and with less headache!

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

That’s a lot of jargon but, like components, we can break it down into less complex chunks.

Error boundaries are React Components

This makes a lot of sense and useful because it’s a concept we have using all along. The difference is that juice was sprayed on it to make it different from a normal component. Still, don’t forget the basic idea that error boundaries are themselves React Components!

Error boundaries catch JavaScript errors anywhere in their child component tree

In case you have forgotten how children component tree work, here is an example:

<ParentComponent>
  <FirstChild>
    <FirstChildDaughter>
    </FirstChildDaughter>
  </FirstChild>
  <SecondChild>
  </SecondChild>
</ParentComponent>

We have two parent and three child components. According to what we have learned so far about error boundaries, we can replicate the above tree to:

<ErrorBoundaryComponent>
  <ParentComponent>
    <FirstChild>
      <FirstChildDaughter>
      </FirstChildDaughter>
    </FirstChild>
    <SecondChild>
    </SecondChild>
  </ParentComponent>
</ErrorBoundaryComponent>

By wrapping the whole tree up in an ErrorBoundaryComponent, we can catch any JavaScript errors that occur in its child components. Cool, right?

Error boundaries log those errors

When errors are caught, we want boundaries errors to do something with them, preferably something to tell us about the. Developers often make use of error logging platforms to monitor errors that occur on their software. With error boundaries, we can do the same.

Error boundaries display a fallback UI

Instead of displaying the whole annoying combo of reds in different shades, you can choose a customized user interface to display when an error occurs. That can come in super handy because it allows you to tailor errors in a style that makes it easier for you to read and scan. Super cool, right?

Like me, you’ll think that this means error boundaries will catch all JavaScript errors. Sadly, that’s not true. Here are errors that they will gracefully ignore:

  • Event handlers
  • Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
  • Server-side rendering
  • Errors thrown in the error boundary itself (rather than its children)

componentDidCatch()

The extra juice that makes a component an error boundary is componentDidCatch() — this is a lifecycle method that works like the JavaScript catch{} block, but for components. When an error is found in a child component, the error is handled by the closest error boundary. Only class components can be error boundaries.

componentDidCatch() accepts two parameters:

  • error: This is the error that was thrown
  • info: An object which contains a trace of where the error occurred

Error Boundary In Action

Say we are working on a feature that lists locations where conferences can be held. Something like this:

See the Pen error boundary 0 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

The application lists locations from the Location component and the individual locations are output as Location Cards. We take a little extra care to ensure the name of each location is rendered in uppercase for consistency. For this tutorial purpose, we will add an empty object to the list of locations.

class Location extends React.Component {
  state = {
    locations: [
      {
        "name": "Ojo",
        "zone": "Lagos State",
        "region": "South West"
      },
      {
        "name": "Ahiazu Mbaise",
        "zone": "Imo State",
        "region": "South East"
      },
      {
        "name": "Akoko-Edo",
        "zone": "Edo State",
        "region": "South South"
      },
      {
        "name": "Anka",
        "zone": "Zamfara State",
        "region": "North West"
      },
      {
        "name": "Akwanga",
        "zone": "Nasarawa State",
        "region": "North Central"
      },
      {
        
      }
    ]
  }
  render() {
    return (
      <div>
        <div>
          <div>
            <h2>Locations</h2>
          </div>
        </div>
        <div>
          {this.state.locations
            .map(location => 
              <LocationCard key={location.id} {...location} />
          )}
        </div>
      </div>
    )
  }
}

const LocationCard = (props) => {
  return (
    <div>
      <hr />
      <p><b>Name:</b> {props.name.toUpperCase()}</p>
      <p><b>Zone:</b> {props.zone}</p>
      <p><b>Region:</b> {props.region}</p>
      <hr />
    </div>
  )
}

const App = () => (
  <div>
     <Location />
  </div>
)

ReactDOM.render(<App />, document.getElementById("root"));

If you run this in the browser, you will see an error similar to this screenshot:

A screenshot of the Type Error providing the error message Cannot read property toUpperCase of undefined. Background color is tan and there is a block of code with a light red background indicating where the error is in the code base.

That’s not totally helpful, so let’s apply an error boundary to handle help us out. First, we’ll create an ErrorBoundary component:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      info: null
    };
  }
  componentDidCatch(error, info) {
    this.setState({
      hasError: true,
      error: error,
      info: info
    });
  }
  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h1>Oops, something went wrong :(</h1>
          <p>The error: {this.state.error.toString()}</p>
          <p>Where it occured: {this.state.info.componentStack}</p>
        </div>
      );
    }
    return this.props.children;
  }
}

An initial state for hasError, error, and info is created. Then, the componentDidCatch() lifecycle method is added. If an error occurs in the constructor, render or lifecycle method of any of its children components, the hasError state will be changed to true. When this happens, the ErrorBoundary component renders and displays the error. But if there are no errors, the children of the ErrorBoundary component are rendered instead as we’d expect.

Next, we need to add both the ErrorBoundary and Location components to our main App component:

const App = () => (
  <div>
    <ErrorBoundary>
      <Location />
    </ErrorBoundary>
  </div>
)

See the Pen error boundary 2 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

We don’t see that annoying TypeError UI anymore! Things are working!

There’s one little thing we can do to improve the app. If you check the code in the demo, you’ll see an empty object we added at the end. Is it possible to have the other credible locations render? Most definitely! Inside the Location component, we can wrap the LocationCard component with the ErrorBoundary component to scope error logging directly to the cards:

class Location extends React.Component {
  state = {
    locations: [
      {
        "name": "Ojo",
        "zone": "Lagos State",
        "region": "South West"
      },
      {
        "name": "Ahiazu Mbaise",
        "zone": "Imo State",
        "region": "South East"
      },
      {
        "name": "Akoko-Edo",
        "zone": "Edo State",
        "region": "South South"
      },
      {
        "name": "Anka",
        "zone": "Zamfara State",
        "region": "North West"
      },
      {
        "name": "Akwanga",
        "zone": "Nasarawa State",
        "region": "North Central"
      },
      {
        // Empty!
      }
    ]
  }
  render() {
    return (
      <div>
        <div>
          <div>
            <h2>Locations</h2>
          </div>
        </div>
        <div>
          {this.state.locations
            .map(location => 
            <ErrorBoundary>
              // Should render all locations, but the empty instance
              <LocationCard key={location.id} {...location} />
            </ErrorBoundary>
          )}
        </div>
      </div>
    )
  }
}

This time, the credible locations show, except the one that is empty. You can choose to wrap the whole component tree with an error boundary component once, or you can wrap different components at strategic places. The decision is up to you.

Wrapping Up

I encourage you to start making use of error boundaries in your applications. Similarly, it’s worth digging in a little deeper. For that, here are some issues in the React repo on Error Boundaries and event handles, go through them so you can see the current state of where things are at:

The post Handling Errors with Error Boundary appeared first on CSS-Tricks.