Front End Web Development

A Lifetime of Nerdery

Css Tricks - Thu, 10/05/2017 - 6:11am

Hi! This is my life story as it relates to my career in tech. I got to give it at ThatConference in August 2017. It was a 90-minute romp through events that, in looking back, had a meaningful impact on my life today.

There are a ton of images in this post. I was gonna lazy load them, but that required removing the src on the <img>s, and that felt bad for syndication and no-js reasons. Anyway sorry about your bandwidth.

These days, the web is a major part of my life. I've managed to make the web both a hobby and a career, and it's stayed fun the entire time.

I get to write about it, help other people learn it, build tools for them to play with it, and talk about it in a variety of contexts.

I'm the co-founder and spend most of my time working on CodePen. I also run CSS-Tricks, which is 10 years old this year.

I podcast about the web with my friend Dave Rupert at ShopTalk Show.

This isn't a presentation specifically about white male privilege, but of course that is there. My life is full of privilege. I often think of how people rarely question what I do and how doors fling open for me. I've never had a co-worker write a manifesto questioning my ability to work in tech.

The rest of this is just a story of my life and I won't be dwelling on this, I just wanted to touch on it as an overarching factor.

I was born at St. Mary's hospital in Madison, Wisconsin. I'm an only child. Fairly introverted. Amateur philosopher. My step dad bought me my first computer ever: a Commodore 64. I'm sure lot of people around my age remember this beauty. This was almost our exact setup. I don't think I had awesome joysticks though.

The command LOAD "*",8,1 is permanently ingrained in my mind. All I knew about it is that it's what you type into the command line after inserting a floppy disk to load whatever was on that disk. Of course, there is a great StackOverflow answer for it now.

We definitely had a disk case like that to hold our huge pile of 5 1/4" floppies! Most of them were games. Turns out my step-dad Johhny answered a newspaper ad of some fella in Janesville, WI who would make copies of games for you for a few bucks. We went down there and hung out in his basement (as the story goes) to get all the games we got.

They were great games! Or at least had me hooked as a kid. Games like Choplifter, where you'd have to drop little bombs (tiny white squares) onto tanks that were trying to kill you while trying to land and rescue people. Commando was super intense. Not only because it was hard, but because there was a lot going on all the time and the music was quite frantic. My favorite was the Winter Olympics because there was so many sub-games, it wasn't so intense, and you could slowly get better with patience and practice. I consider the Commodore 64 such a big deal in my life not only for the obvious (early computer access) but because of this upgrade: the Commodore 128. My parents saw how into computers I was and got me a better one when it was possible. That was setting an early and positive precedent. Come elementary school, we had these Apple ]['s. It wasn't a regular part of the curriculum (or so I remember) and probably would have been something I ignored, but because of my home experience with computers, I took to it right away. I like being the kid that knows stuff. You know, like a nerd. Gaming was a big deal on the Apple too, with games like Odell Lake which was all about decision making. I think there are people that "remember" this game (Oregon Trail) that never even played it. We had LEGO LOGO in that class, which was a way to control motorized legos through code. That would be extremely cool even now. Take that, nodebots. That's my mom and stepdad. His name is Johnny Beyler. He and his two brothers own a screen printing business in Madison, Wisconsin called Advertising Creations, as passed down from their father. John has a son also named John (my stepbrother), who worked at the shop. (Little) John was friends with a guy named Steve Raffel who also worked at the shop. This is Steve much later in life. They lived together for a while, in a little white house on the East side of Madison. I have one memory of going there as a kid, and seeing Steve's computer screen, where he was working on some really amazing looking computer graphics. A 3D world you could move in and open and close castle gates. Setting the time stage a bit, this was about the same time as DOOM was hitting shelves and having a massive impact on computer gaming. Steve (and his brother Brian) went on to form Raven Software. The produced little games like HERETIC. (!!) And HEXEN. (!!) They were ultimately purchased by Activision, but still work there and operate under the name Raven Software. Looks like they still pay respect to those days. These days they work on little games like Call of Duty. (!!) And hire for roles like "Weapons Artist". I'll leave it up to you to decide if you want to finish reading this presentation or quit everything and apply for that job. My next computer was a Macintosh Performa 636CD. It was a serious machine to essentially buy for a kid. I'm sure they called it a family computer but they knew it would essentially be mine. It had a video on it called "mold growing on bread" that I watched over and over. It's weird to think games like DOOM existed, but it was still fascinating to be able to watch videos on a computer. I was just headed into Verona Area High School. Ultimately I got one of these bad boys for the computer, hitching it up to the information age. One of the first things I did was call up "bulletin boards", which were essentially phone numbers you could call with your modem and it would transmit a basic UI you could interact with. You could play dumb little games with other people. Again, weird to think games like DOOM existed, but this was ALSO cutting edge in it's own way. Bulletin boards were definitely pre-world-wide-web, and so were services like GEnie that you dialed into and hooked you into a network. Imagine PAYING BY THE HOUR these days for a service. It wasn't long before AOL started covering the entire planet with AOL CD's. I was in. AOL was incentivized to keep you online a lot, as they also charged hourly after your monthly quota. They had online games! I immediately got into one called Gemstone III (now IV) that was an early MMORPG. Gemstone was entirely a command line interface. A pretty sophisticated one, really, that accepted complex commands to do all kinds of things. I couldn't have possibly been more into it. It was roleplaying adventure at it's finest. I played somewhat actively for 10 years, and still pop in once in a while. Imagine that, a text-based MMORPG still actively running and maintained. That's the power of charging monthly for something! In high school, I took an elective programming class with Mr. Scott. Turbo Pascal was the flavor of the day. Beyond the basics, one of the first projects I undertook was Conway's Game of Life. You have a grid. Cells in the grid are either on or off. Cycles (time) passes in the game and the cells live or die (on or off) based on a simple set of rules. To this day, I collect interesting examples of the Game of Life on CodePen. We didn't have "the internet" in the computer labs. It wasn't even really a thing yet. But all the computers were networked via AppleTalk. That allowed us to do stuff like print to a shared printer, but also opened some fun programming doors. My next project was a version of Battleship. Hey, I was already comfortable working in grids! But this time, it was a turn-based game playable over AppleTalk. Playing over a network was incredible. Another huge aspect of high school was getting into ceramic art. Verona Area High School has an amazing ceramics program. Better than most colleges. This is an obvious time to mention privilege. It's very clear to me, looking back, how many opportunities were just laying around for me. I basically followed my friend Jeff Campana into ceramics, who was engrossed by it from day one. He was great at it back then, and of course is much better now (he's made an entire life from being a professional artist). Another good friend of mine is Jeff Penman. Jeff originally moved to town when his dad became an early partner at Raven Software! Jeff's dad Victor ultimately formed his own company, Evermore Entertainment. Evermore had the unbelievable job of building the first-ever computer program for Dungeons & Dragons players: Core Rules. For us kids, it meant cool things like getting to go to GenCon with staff badges. Evermore also meant we had an office for LAN parties. (Like a real office, not a garage.) Games over a network, of course! Games like WarCraft. And StarCraft. I watch competitive StarCraft videos to this day. My least favorite kind of game is me vs. you. Us vs. them is more fun. At least we can talk and strategize together then. Everyone working together against a huge "problem" is my favorite type of "game". Even bar games like "find the difference" are more fun when everyone is huddled around the machine than it is competing against each other. I'd rather work with you to build the tallest tower we can with Scrabble tiles than actually play Scrabble against you. I went to the same college most of my friends went to. Because friends. I couldn't get into a really good school anyway, as I've never been a good-grades type. I chose "Management Computer Systems" at the University of Wisconsin-Whitewater.

I joined the Green Party in college. They seemed like the closest match to how I was feeling at the time. I founded Whitewater United for Peace. My main political feeling at the time was related to the absurdity of war, so I wanted to be mad about that, officially. Jam bands and hippies were the official music and culture around what I was doing, and I was all into it. Interestingly enough, that world is super compatible with being a nerd. For example, trading and collecting live shows. I started bartending in college, at, of course, the bar that was most aligned with being a hippie bar. All the peace-loving, music-loving, and as it turns out, art-loving people all hung out at The Brass Rail. I became the manager eventually. Thinking back on that time, it was mostly very positive. I do remember the feeling establishing itself that I felt a bit broken though, not like everyone else. I didn't want to go to barhopping or to the afterparty. It felt good, many years later, to understand all my introverted traits. My way in was through bluegrass jams. By this time I had bought some instruments and was enamored with bluegrass. I'd go to bluegrass jams all around the area. They were always very welcoming, educational, and fun. I decided to start throwing my own bluegrass jam at the Brass Rail. People came to watch! People came to play, too, and the regulars that clicked the best, including me, formed a little band. Here's us, the Missing String Band. We'd play anywhere, anytime, for anything. For years we played a weekly gig at a brewery in Mt. Horeb called The Grumpy Troll. Every year we'd round up as many friends as we good and head down to Graves Mountain in Virginia for camping and jamming good times.

The actual software training we got was pretty focused on Illustrator, Photoshop, and InDesign. I'm pretty grateful for that. Also, I appreciate that higher education is more concerned about concepts and learning how to learn and all that, and consider specific software training more of a trade school thing. But still, it was somewhat disappointing to not learn anything web related.

The closest we got was Director (Macromedia at the time). All that keyframes stuff in Director was the interface for Flash as well, and Flash actually was for the web, so I was into Flash for that reason. I was back in the land of Macs! All those formative years with Macs, all that high school time with Macs... it made having to switch to PCs for those Management Computer Systems major years rather painful. Coming back to graphic design classes, I was back in comfortable territory.

I wanted a web job, but I didn't have the skill. My exposure and experience in the print industry lead me that direction after college. I worked for a electronics/furniture/applianaces place as my first job out of college doing design and prepress work. They had a website too lol. Whenever I asked to work on that, I was denied. The main work was the production of a weekly flyer like this. It was a surprising amount of work every week to produce something so awful looking. Thus began my first career in prepress. The only creativity involved was finding creative solutions to technical problems with design documents. It's quite a nerdy job in it's own way, and there were parts of it that I really enjoyed. Design documents come to print shops in pretty rough shape. Even very good (and print-aware) designers send documents that need quite a bit of work before they actually hit a big press. There are more than passing similarities between a prepress tech and being a CSS developer. I was converting designs into a final product, solving many problems along the way. How are the edges handled? Are the colors defined correctly? How do the pages back up to each other? How is the image resolution? Spacing? Alignment? The end of the line for prepress, in an offset lithography shop, is metal plates. One for each color or varnish or whatever. Prepress was, in a way, rapidfire problem solving. Add that to already a lifetime of computer nerdy and computer problem solving as a hobby, and my confidence level at solving computer problems was starting to be pretty dang high. I bounced around prepress jobs, but all the while I knew I wanted a web job. I was making websites on the side, for fun and to learn. Ultimately, my mom heard of a job opening at a small design shop in Madison. By some miracle (and their desperation), I got the job. My first major job there was a website for a magician who really needed to sell tickets online. I was in no way qualified for that, but we got it done! We had lots of clients though, and a lot of them were wanting to move to the web. This was very much in the heat of the "we need to get on the web!" period for companies. We helped every single one of our clients. Even if we had no idea what we were doing at first. I've always been attracted to the idea of side and passive income. I mowed the lawns at my apartment building for ten dollars a week. Of course, I would have rather been extracting money from the internet. CSS-Tricks was born at this time. I was learning a lot of the web, and I learned even more by writing it down, as awful as that writing was in the early days. I had been working at Chatman Design for a while, I was 27 years old, and I'd never lived outside of a 60 mile radius of Madison, Wisconsin. I didn't love that. It was too comfortable. My work hardly ever required direct client meetings. I needed to communicate with my boss and clients, but that all happened over chat and emails, so I forced the issue of working remotely. I moved out to Portland, Oregon with just what would fit in my Saturn L200. I really liked Portland, but I didn't exactly carve out a life there. I remember trying to go to meetups for web and blogging stuff, and being so nervous I wouldn't talk to anybody and just leave. The remote work part was easy though. I got plenty of work done. After a bit less than 2 years, I had another friend in Chicago who needed a roommate, and I figured I'd try that. I also wasn't able to carve out a life in Chicago, despite at least some minor effort. It's still a pet peeve of mind when people announce hate for an entire city. Cities are too complicated for that. One experience at one point in time in one part of a city can be bad (as was mine), but that doesn't make the entire city bad. I'd been working for years now professionally as a web designer, so my confidence in building for the web had grown. That was a result of doing tons of work literally at work, but also maintaining doing web work as a hobby, so taking any chance I could to build a site for someone. It's very worth noting how empowing WordPress was for me this entire time. It was the only tool I used, but it was for about 90% of the work I did both personally and professionally. Especially if the site required functionality beyond what I knew I could write myself. I even co-authored a book about WordPress, with Jeff Starr. There were a number of interesting things we did with it (lays flat! free updates forever!) but perhaps the most relevant is that we knew the power of writing. So before we released the book, we released a blog of the same name. That gave us the most powerful marketing tool we could have for the ultimate sale of the book. I designed the cover it. Looking back now it looks like I was trying to channel Tim Chatman, my boss at Chatman Design.

I was living in Chicago, writing Digging into WordPress, working at Chatman Design, and building CSS-Tricks at this time.

Dan Denney invited speak at the first-ever Front End Design Conference, which was a wonderful honor and helped get the career ball rolling for me even more.

At Front End Design Conference, I met Kevin Hale (a fellow speaker) and also ended up meeting the rest of Team Wufoo at the afterparty.

They wanted to meet me, as I was already a very public superfan of Wufoo. I would write about it and praise how useful it was, particularly as a lone developer at a small agency with loads of sites.

Not long after meeting them, they offered me a job and I couldn't get out of Chicago fast enough.

While Wufoo was a "remote" team, everyone lived in Tampa / St. Petersburg, and we got together once a week for a meeting.

Wufoo leveled up my abilities as designer and developer in big ways. This wasn't just hacking things together until they worked and the client was happy. This was working with extremely talented web workers using modern tools and modern workflows. Not only did I get to work on Wufoo the app itself, but I got to do industry research, marketing, blogging, and more public speaking. Less than 2 years after starting at Wufoo, the founders decided to sell to SurveyMonkey. SurveyMonkey was based in Palo Alto, California, and they wanted us to all move out there, which we all did. Palo Alto was a very different place! All the things you think about are probably true. Every restaurant and coffeeshop is full of nerds talking about VC. Electric cars everywhere. Perfect weather. Expensive.

SurveyMonkey is a great place. An app with a clear value proposition that really helps people. They take care of their employees well, have a gorgeous office, and a pretty good culture.

Still, it just wasn't for me. I didn't like be obliged to go into an office. I didn't love my exact position and who I had to report to. I didn't feel like I could enact any useful change there.

And so CodePen began! It began as a bit of a weekend project where I asked for help from Tim Sabat and Alex Vazquez, who I worked with both at Wufoo and Survey Monkey and who I had become good friends with.

The idea and scope behind CodePen quickly grew up. We had weekly meetings at The Old Pro. They had good wings. After I left SurveyMonkey, there was a little panic that I wouldn't have nearly as much money coming in. A problem, particularly in a city like Palo Alto, and during a time when we hadn't even thought about ways for CodePen to make money. My solution was to double down on CSS-Tricks, trying to form it into more of a legit business. That meant revamping the website, and what better thing to record and talk about for a website about websites! Backers to the Kickstarter could watch that whole process. In the end, it wasn't much of a money maker, but it literally did "kickstart" the business. My system for showing demos on CSS-Tricks was pretty rudimentary. Essentially toss a .php file up on a server showing off the complete demo. PHP just so I could include a header and footer. You know, branding. An early mockup of CodePen, before it was called CodePen. This kind of layout was pioneered by JSFiddle, and is clearly the nicest way to look at some code, particularly front end code that produces a visual demo. As much as CodePen has grown up, the heart of it is still this same idea. Although the homepage of it has much for focus on community. What is awesome on CodePen today? Just look at the homepage. That community aspect is everything to me. People have profiles on CodePen that are, in sometimes a very literal sense, their portfolio. Maybe a year into Working on CodePen, the three of us co-founders decided to take a real run at making CodePen a real business. We're still at it! We're definitely a real business, but we have a long way to go.

It's not just us. All of these people made CodePen what it is.

Perhaps this is a bit weird, but it feels a bit like playing a game. One of those games that really drew me in. One that you're playing with lots of other people, and all toward a common goal.

Let's wrap this up with some big fancy lessons.

ok bye bye.

A Lifetime of Nerdery is a post from CSS-Tricks

Vue.js Style Guide

Css Tricks - Wed, 10/04/2017 - 12:00pm

"Style guide" as in, if you're writing JavaScript using the Vue framework, these are some guidelines they suggest you follow. Not to be confused with a pattern or component library, which happens.

Things like using multi-word PascalCase components and abstracting complex logic away from templates. There are a couple dozen of them nicely documented with good and bad examples. This isn't entirely uncommon. I know WordPress has guidelines for this kind of thing.

These are in an unusual category of style guide, where it's not like this is how you should structure, format, and name code, it's this is how you should structure, format, and name code in this framework. The rabbit hole could get deep here. This is how we write code at WidgetCorp. This is how we write JavaScript at WidgetCorp. This is how we write JavaScript when using Vue at WidgetCorp during full moons.

I also have a theory.

Direct Link to ArticlePermalink

Vue.js Style Guide is a post from CSS-Tricks

Keeping track of letter-spacing, some guidelines

Css Tricks - Wed, 10/04/2017 - 4:55am

Considering that written words are the foundation of any interface, it makes sense to give your website's typography first-class treatment. When setting type, the details really do matter. How big? How small? How much line height? How much letter-spacing? All of these choices affect the legibility of your text and can vary widely from typeface to typeface. It stands to reason that the more attention paid to the legibility of your text, the more effectively you convey a message.

In this post, I'm going to dive deep into a seemingly simple typesetting topic—effective use of letter-spacing—and how it relates to web typography.

Some history

Letter-spacing, or character spacing, is the area between all letters in a line of text. Manipulation of this space is intended to increase or decrease the visual density of a line or block of text.

When working in print, typographers also refer to it as tracking. It is not to be confused with kerning, which refers to the manipulation of space between two individual letters. Kerning is not usually practiced on the web.

See the Pen.

Historically, manipulating letter-spacing was a technique frequently used when laying out newspapers. The pressure of quick deadlines meant that reporters didn't have the luxury of being able to rewrite sentences to better fit the physical space allotted for them on the page. To work around this, designers would insert spacing between the letters—first by hand and then later digitally—so that a line of type would better fill the allotted space.

On the web where available space is potentially infinite, letter-spacing is usually employed for its other prominent historical use case: creating a distinct aesthetic effect for content such as titles and headlines, pull quotes, and banners.

While fine typographic control on the web is only a recent development, the ability to perform letter-spacing has been around since CSS1. Naturally, the name of this property is called letter-spacing.

letter-spacing accepts various kinds of lengths as a value. Unlike its physical counterpart, it can be set to a negative measurement, which moves the letters closer together instead of further apart. When setting print type, no competent typesetter would have cut chunks out of their lead type to achieve this effect. However, when your letters are virtual, you can do whatever you want with them!

Stealing Sheep

In researching the history of letter-spacing, you're likely to run across a famous quote by type designer Frederic Goudy. The—ahem—clean version is, "Anyone who would letter-space lower case would steal sheep." Essentially, Goudy is saying that manipulating type without knowing the rules is bad.

Some have taken this quote at face value and sworn to never apply letter-spacing to content containing any amount of lower case text. While I would never presume to be as skilled or as knowledgeable about typography as Goudy, I would caution against the pitfalls of dogmatism.

There are situations where it would be advantageous to apply letter-spacing to large sections of text, so long as it is in the service of optimizing legibility. For example, a judicious application of letter-spacing applied to legal copy or agate provides a much-needed assist in a situation where the reader is navigating small, dense, jargon-filled content.

Much like practicing good typography, writing great CSS is all about minding the details—even a single property can contain a great deal of hidden complexity. Understanding the history, capabilities, and limitations of the technology allows for the creation of robust, beautiful solutions that everyone can use, regardless of device or ability.

If you would like to manipulate the letter-spacing of text on your website, here are some guidelines on how to do it well and avoid making mistakes.

Use letter-spacing, not spacing characters

In print, creating space between each letter in a line of metal or movable type historically involved inserting small pieces of metal between each letter. However, on the web you want to avoid adding any extra glyphs—such as spacing characters—between each typed letter. If you need to achieve the visual effect of letter-spaced type, use the letter-spacing property. This one might seem obvious, but you'd be surprised!


If spacing characters are used, future styling changes will be more difficult to make and maintain. Every typeface has different widths. It is harder to predict or control how potential redesigns might behave, especially when making typesetting decisions for larger sites with a lot of varied content.

See the Pen.

If you find this is an emergent behavior amongst multiple site authors, you should investigate codifying it by updating site styles to reflect this desired aesthetic. This may also necessitate talking to designers to update style guides and other relevant branding documents.


If letters are separated by spacing characters, some screen readers will read each letter individually instead of the whole word. In this scenario, usability is sacrificed for the sake of authoring ergonomics—browsing becomes labored and people get unnecessarily excluded from using your site.

Imagine for a moment that your eyesight isn't as great as it is now. Your experience on the web would be a lot like this:

This issue won't trigger automated accessibility checks, so it's important to audit manually. Like two spaces after a period, this practice is a bad habit, so further violations can usually be found on a per-author basis.

Non-unitless values

The letter-spacing property uses a non-unitless value to determine how far apart letters are spaced. While CSS offers a range of units to choose from, there are some values to be avoided:

Pixels and other absolute units

Much like manually inserting spaces to create a letter-spacing effect, absolute units such as pixels also make it difficult to predict what might happen when you inevitably update or change any type styles or faces. Unlike relative units, these static units will only scale proportionately to themselves when zoomed. Some older browsers won't scale them at all.

In terms of maintainability, static units are also problematic. What might work well defined in pixels for one typeface might not look great for another, as different typefaces have different widths for their glyphs. If you ever change your brand's typeface, updating precisely measured pixel values across your entire site becomes a large chore.

Relative units

The size of a relative unit is determined by measuring it against the size of something else. For example, viewport units size things relative to the browser's height and width—something styled with a width: 5vw; will have a width of 5% of the width of the browser (admittedly an oversimplification, this isn't a post about the nuances of browser UI).

For letter-spacing English and other Romance languages, the em unit is what you're going to want to use.

Historically, ems were measured by the width of a capital M—typically the widest character in the alphabet—or later, the height of all the metal type in the font's set. In web typography, ems are potentially based off of a stack of things:

  1. The browser's default font size (typically 16px, but not always).
  2. A user-specified default font size.
  3. The font size declared on the root of the page (typically applied to the <body> tag).
  4. The font size declared on a containing parent element.
  5. The font size declared by a style.
  6. The font size set by a special operating mode such as browser zoom or extension, OS preferences, etc.

In addition to the nerdish pride you'll feel paying homage to the great typographers of generations past, em-based letter-spacing will always be relative to the font size you've declared. This gives the assurance that things will always be properly and proportionately scaled.

rems, ems younger sibling, operate in a similar way. The main difference is that they are always proportional to the root font size (but are still affected by things like special browser operating modes).

While the ease of using rems for letter-spacing might seem attractive, I hope you’ll consider Progressive Enhancement. The same older browsers you’d worry about choking on pixel scaling probably won’t have rem support. Save your future self the hassle of the inevitable bug fix and use ems in the first place.


Armed with the knowledge that you can gracefully and resiliently adjust letter-spacing, there’s one last thing to consider: While glyphs that are jammed too close together are obviously difficult to read, text that has been letter-spaced too far apart also has a negative impact on legibility.

When the distance between glyphs is too great, words start to look like individual letters. This can potentially affect a wide range of your audience, including people with dyslexia, people new to the language, people with low vision, etc.

See the Pen.

Like with the manually manipulated spacing issue discussed earlier, this issue potentially won't be caught by an automated accessibility check. Unfortunately, there is no magic formula for determining how far is too far for spacing characters apart. Since different typefaces have different character widths, it is important to take a minute to review and determine if your lines of text are both readable and legible when manipulating the letter-spacing.

Use text-transform

It is common to see type set in all capital letters also use letter-spacing. This is to lessen the visual “weight” of the page as a whole, so the eye isn't unnecessarily distracted while reading through it.

The text-transform property controls how text gets capitalized. There's a subtlety to this, in that the transform happens on the rendered page, and not in the source HTML. So, a string of text authored as, “The quick brown fox jumped over the lazy dog.” and styled with text-transform: uppercase; will be rendered as “The quick brown fox jumped over the lazy dog.”

Choosing the right amount of letter-spacing to go with text via text-transform is more an art than a science, and there are some hidden complexities and bad behaviors to be aware of:


If you're picking up on a pattern here, it's that you want to let CSS do what it was designed to do: control the look of the page without affecting the underlying semantics of the HTML markup.

If you use a series of hand-typed capital letters to create the effect, it will be treated in much the same way as using typed spaces—some older screen readers will read each letter individually. While this is fine for most acronyms, content capitalized solely for the sake of aesthetics should have this transformation performed via styles.

And again, if this manual effort is a pattern amongst your site authors, investigate codifying the behavior and swap in text-transform instructions. Not only will you be doing your users a solid, but you're also being a good coworker by saving them a little hassle and effort.

Reading comprehension is another factor to consider. We read written language by anticipating patterns of letters that will be in words, then going back to verify. Large areas of text set in all caps makes it difficult to predict these patterns, which reduces both the speed of reading and interpretation.

User experience

Micro-interactions are frequently overlooked and undervalued when sprinting to get a project out the door, but go a long way in creating favorable and memorable experiences. One such micro-interaction is proper use of text-transform.

When copying text, certain browsers honor the content in the source, and ignores any text transforms applied to it. If we copied our "The quick brown fox" example above in Firefox or Edge and pasted it, we would see the text is not set in all uppercase.

Some may argue that styled presentation takes priority, but I view browsers that don't support this preservation of author intent as being incorrect. If you do not have the time, resources, autonomy, or technical know-how to convert this text back to its authored case it becomes non-trivial to reformat. In situations where this content must be manually migrated into other systems, it unnecessarily introduces the potential for errors.

Feeling fancy?

Still with me? Here's your reward! With the confidence that we're now letter-spacing our type properly, we're going to dig into some of the fun stuff:

Special units

No, we're not talking about Seal Team 6. If you spent some time on the MDN page discussing the various units available to work with, you might have noticed a few interesting measurements in the subsection called Font-relative lengths:

  • ex, which represents the font's x-height.
  • cap, which represents the height of the font's capital letters.
  • ch, which represents the width of the font's zero (0) glyph.

If you want to really double-down on your typography, you can use:

  • ex for letter-spaced type set to use small caps (more on this in a bit).
  • cap for letter-spaced type transformed to all uppercase.
  • ch for letter-spaced monospace fonts.

While the support for these units varies, CSS' @supports allows us to confidently write these declarations while providing fallbacks for non-compliant browsers.

.heading-primary { color: #4a4a4a; font-family: "ff-tisa-web-pro", "Tisa Pro", "FF Tisa Pro", "Georgia", serif; font-size: 2em; letter-spacing: 0.25em; /* Fallback if the `cap` unit isn't supported */ line-height: 1.2; text-transform: uppercase; } @supports (letter-spacing: 0.25cap) { .heading-primary { letter-spacing: 0.25cap; /* Quarter the font's capital letter height */ } } OpenType features

The history of typography is full of special treatments for specific use cases where the default presentation may not have been sufficient to convey meaning effectively. Some treatments were to help reinforce visual tone, while others were more pragmatic—aiding the ease of interpretation of the text.

See the Pen.

OpenType embraces this history and allows the savvy typographer to use these specialty treatments, provided the font supports them. For digital typography, most companies that sell professional typefaces will tell you what is available.

Adobe Typekit buries what features are available in the info icon located next to the "OpenType Features" checkbox in their Kit Editor. Thisarmy's Google OpenType Feature Preview allows you to browse through Google Font's library and toggle available features.

Unfortunately, a lot of other free font hosts do not. In order to determine if the typeface you've selected has the specific glyphs needed to support these features, you can test it in the browser. If you have a copy installed on your computer, you can also view the font's character map (Character Map for Windows, Font Book for Mac).

These two programs allow you to view every glyph included in a typeface—hidden treasure awaits!

Most OpenType features will automatically swap in if enabled and the specific character combinations are typed out. Thanks to some clever engineers, this substitution will not affect things like searching, translating, or pasting/changing to a font that lacks support.

If your font does have support for OpenType features, here are some considerations to have in mind when letter-spacing:


Common and discretionary ligatures are special glyphs that combine two characters commonly found next to each other. Historically, they were used to address common kerning issues, and also to save the lead type for use elsewhere.

With regards to letter-spacing, you'll want to make sure ligatures are disabled to prevent something like this from happening:

#ProTip: When using letter-spacing != 0, disable ligatures through font-feature-settings. Otherwise this happens.

— Lea Verou (@LeaVerou) July 6, 2014

You might also be considering using a styled span tag to approximate a ligature and kern two characters closer together. This is a clever idea, but can be problematic when read by a screen reader:

Swashes and Alternates: Titling, contextual, stylistic, historical

These special features typically adjust the presentation of the font to adjust the tone, or to make special flourishes and commonly repeated characters more distinct. These features are less common, but most professional typefaces will contain at least one treatment.

Much like ligatures, the presentation of letter-spaced type can affect these features. It's good to test how it will look on a wide variety of content before pushing styles live—lorem ipsum might not catch it.

Small caps

A lot of word processing programs allow you to create faux small capitals the same way they allow you to create faux bold and italic styles. The trouble with these faux styles is they are inferior counterfeits. Real bold, italic, and small cap styles are specifically designed to use the same proportions and metrics the rest of the typeface uses. Faux styles are a one-size-fits-all solution and are about as elegant-looking as a cow falling down the stairs.

While CSS does have a font-variant: small-caps; declaration, it really shouldn't be used unless the font includes actual OpenType small cap glyphs. Much like word processor faux small caps, CSS-created faux small caps are a distorted photocopy of the real thing.

If your typeface does support small caps, chances are good that the typographer who designed it baked the ideal amount of letter-spacing into their glyphs. Because of this, you may not need to manually letter-space and can rely on their good judgment.

Case-sensitive forms

This feature renders glyphs that are designed to look good when set next to anything set in all caps. Thanks to things like hashtags (#) and at symbols (@), we're enjoying a Renaissance of non-alphanumeric characters being placed alongside regular content. If your font supports them and you're using letter-spaced all caps styles somewhere, I say include 'em!

CSS custom properties, preprocessors and utility classes

One of the aims of a mature website is to have a codebase that is easy to understand and maintain. CSS Custom Properties and CSS preprocessors such as Sass or PostCSS offer features like variables that allow developers to codify things like measurements that are repeated throughout the source code.

For letter-spacing, variables can be a great way to ensure that developers don't have to guesstimate what the value is. A system containing pre-defined and easy-to-understand measurements such as $tracking-tight?/?$tracking-slight?/?$tracking-loose let people working on the site not waste time deliberating on what best matches the design. Designers would be wise to use the same naming convention the developers do for these agreed-upon measurements.

Utility classes—a CSS methodology that “applies a single rule or a very simple, universal pattern”—can also take advantage of this formalizing of measurements. By taking these pre-defined groupings of declarations in your design system and turning them into single-purpose classes, you can add a lot of flexibility and modularity to how elements on your site are described:

<section class="c-card"> <h3 class="u-heading-secondary u-tracking-slight u-all-caps"> Our services </h3> … </section>

This can be especially handy if your organization has a large site with a lot of different components and varying levels of access to the site source code. Authors who only have access to a post authoring environment—including a HTML/Markdown view—will be more inclined to stay within established styles if they are made aware of them and they allow for the flexibility they need.


Typography is part of everyone's reading experience, yet something that most do not think about very much. By better understanding its history, strengths, and weaknesses, we are able to craft clear and effective reading experiences for everyone.

Keeping track of letter-spacing, some guidelines is a post from CSS-Tricks

REST versus GraphQL

Css Tricks - Wed, 10/04/2017 - 4:54am

I think the jury is in: GraphQL is a winner for developers consuming APIs. We format a request for the exact data we want, and the endpoint coughs it up. What might have been multiple API requests and manually stitching together data, is now one in just the format we want.

I've heard less about whether GraphQL is ideal for the providers of those APIs. I imagine it's far easier to cache the results at specific URL's with a REST structure, as opposed to a single URL in charge of any request. But I'm no server guru.

This tool is pretty fascinating in that is allows you to build your own little GraphQL backend and then run queries against it and see the results.

Direct Link to ArticlePermalink

REST versus GraphQL is a post from CSS-Tricks

Scrolling your website past the iPhone X&#8217;s notch

QuirksBlog - Wed, 10/04/2017 - 4:32am

During the introduction of the iPhone X a hilarious gif made the Twitter rounds, showing a list scrolling past the new notch.

I asked the question any web developer would ask: “Hey, is this even possible with web technology?” Turns out it is.

(We should probably ask: “Hey, is this a useful effect, even if it’s possible?” But that’s a boring question, the answer being Probably Not.)

So for laughs I wrote a proof of concept (you need to load that into the iPhone X simulator). Turns out that this little exercise is quite useful for wrapping your head around the visual viewport and zooming. Also, the script turned out to be quite simple.

I decided to give this script an old-fashioned line by line treatment like I used to do ten years ago. Maybe it’ll help someone wrap their head around the visual viewport, and performance, and potential viewport-related browser incompatibilities.


First, let’s repeat some definitions:

  • Visual viewport: the part of the site the user is currently seeing. Changes position when the user pans, and changes dimensions when the user zooms.
  • Layout viewport: the CSS root block, which takes its width from the meta viewport tag (and can thus become so narrow that it neatly fits on the phone’s screen). Plays no part in what follows.
  • Ideal viewport: the ideal dimensions of the layout viewport according to the phone manufacturer. The layout viewport is set to the ideal viewport dimensions by using <meta name="viewport" content="width=device-width,initial-scale=1"> The demo page does so.

See my viewports visualisation app for an overview of how all this stuff works in practice.


This is the CSS I use:

li { font-size: 9px; border-top: 1px solid; border-width: 1px 0; margin: 0; padding: 3px 0; padding-left: 10px; transition-property: padding; transition-duration: 0.2s; } li.notched { padding-left: constant(safe-area-inset-left); }

The purpose of the script is to change the class names of LIs that are next to the notch to notched. That changes their padding-left, and we also give that change a nice transition.

Preparing the page window.onload = function () { allLIs = document.querySelectorAll('li'); if (hasNotch()) { window.addEventListener('orientationchange',checkOrientation,false); setTimeout(checkOrientation,100); } else { allLIs[0].innerHTML = 'Not supported. View on iPhone X instead.'; } }

First things first. Create a list allLIs with all elements (in my case LIs) that the script is going to have to check many times.

Then check for support. We do this with the hasNotch() function I explained earlier. If the device has a notch we proceed to the next step; if not we print a quick remark.

Now set an orientationchange event handler. The script should only kick in when the notch is on the left. After we set the event handler we immediately call it, since we should run a check directly after the page has loaded instead of waiting for the first orientationchange, which may never occur.

There’s an oddity here, though. It seems as if the browser doesn’t yet have access to the new dimensions of the visual viewport and the elements until the JavaScript execution has fully come to a stop. If we try to read out data immediately after the orientationchange event (or, in fact, the scroll event), without giving the Javascript thread an opportunity to end, it’s still the old data from before the event.

The solution is simple: wait for 100 milliseconds in order to give the browser time to fully finish JavaScript execution and return to the main thread. Now the crucial properties are updated and our script can start.

Checking the orientation function checkOrientation() { if (window.orientation === 90) { window.addEventListener('scroll',notchScroll,false); setTimeout(notchScroll,100); } else { window.removeEventListener('scroll',notchScroll,false); for (var i=0,li;li=allLIs[i];i+=1) { li.classList.remove('notched'); } } }

Checking the orientation is pretty simple. If window.orientation is 90 the phone has been oriented with the notch to the left and our script should kick in. We set an onscroll event handler and call it, though here, too, we should observe a 100 millisecond wait in order to give the properties the chance to update.

If the orientation is anything other than 90 we remove the onscroll event handler and set all elements to their non-notched state.

Main script

The main script is called onscroll and checks all elements for their position — and yes, every element’s position is checked every time the user scrolls. That’s why this script’s performance is not brilliant. Then again, I don’t see any other way of achieving the effect, and I heard rumours that a similar technique performs decently on iOS. Anyway, we can’t really judge performance until the actual iPhone X comes out.

var notchTop = 145; var notchBottom = 45;

Before we start, two constants to store the notch’s top and bottom coordinates. There are two important points here:

  1. The coordinates are calculated relative to the bottom of the visual viewport. If we’d use coordinates relative to the top, incoming and exiting toolbars would play havoc with them. Using bottom coordinates is the easiest way to avoid these problems.
  2. What coordinate space do these coordinates use? This is surprisingly tricky to answer, but it boils down to “a space unique to iOS in landscape mode.” I’ll get back to this below.

Now we’re finally ready to run the actual script.

function notchScroll() { var zoomLevel = window.innerWidth/screen.width; var calculatedTop = window.innerHeight - (notchTop * zoomLevel); var calculatedBottom = window.innerHeight - (notchBottom * zoomLevel);

The crucial calculations. We’re going to need the current zoom level: visual viewport width divided by ideal viewport width. Note that we do not use heights here, again in order to avoid incoming or exiting toolbars. Width is safe; height isn’t. (Still, there’s an oddity here in Safari/iOS. See below.)

Now we recast the notch coordinates from relative-to-bottom to relative-to-top. We take the current height of the visual viewport and subtract the notch coordinates relative to the bottom, though we first multiply those coordinates by the zoom level so that they stay in relative position even when the user zooms.

The beauty here is that we don’t care if the browser toolbar is currently visible or not. The visual viewport height is automatically adjusted anyway, and our formula will always find the right notch position.

var notchElements = []; var otherElements = []; for (var i=0,li;li=allLIs[i];i+=1) { var top = li.getBoundingClientRect().top; if (top > window.innerHeight) break; if ((top < calculatedBottom && top > calculatedTop)) { notchElements.push(li); } else { otherElements.push(li); } }

Now we loop through all elements and find their positions. There are several options for finding that, but I use element.getBoundingClientRect().top because it returns coordinates relative to the visual viewport. Since the notch coordinates are also relative to the visual viewport, comparing the sets is fairly easy.

If the element’s top is between the notch top and notch bottom it should be notched and we push it into the notchElements array. If not it should be un-notched, which is the job of the otherElements array.

Still, querying an element’s bounding rectangle causes a re-layout — and we have to go through all elements. That’s why this script is probably too unperformant to be used in a production site.

There’s one fairly easy thing we can do to improve performance: if the element’s top is larger than the visual viewport height we quit the for loop. The element, and any that follow it, are currently below the visual viewport and they certainly do not have to be notched. This saves a few cycles when the page has hardly been scrolled yet.

while (notchElements.length) { notchElements.shift().classList.add('notched'); } while (otherElements.length) { otherElements.shift().classList.remove('notched'); } }

Finally, give all to-be-notched elements a class of notched and remove this class from all other elements.


There’s a fairly important caveat here. I moved the actual assignment of the classes outside the for loop, since this, theoretically, would increase performance as well. There are no actual style changes during the loop, so we can hope the browsers don’t do a re-layout too often. (To be honest I have no clue if Safari/iOS does or doesn’t.)

This sounds great, but there’s a problem as well. Notched elements get a larger padding-left, which, in real websites, might cause their content to spill downward and create new lines, which makes the element’s height larger. That, in turn, affects the coordinates of any subsequent elements.

The current script does not take such style changes into account because it’s not necessary for this demo. Still, in a real-life website we would have no choice but to execute the style changes in the main loop itself. Only then can we be certain that all coordinates the script finds are correct — but at the price of doing a re-layout of the entire page for every single element.

Did I mention that this script is just for laughs, and not meant to be used in a serious production environment? Well, it is.

Browser compatibility notes

This script is custom-written for Safari/iOS. That’s fine, since the iPhone X is the only phone with a notch. Still, I would like to point out a few interesting tidbits.

getBoundingClientRect is relative to the visual viewport in some browsers, but relative to the layout viewport in others. (Details here.) The Chrome team decided to make it relative to the layout viewport instead, which means that this script won’t work on Chrome.

As an aside, it likely will work in Chrome/iOS and other iOS browsers, since these browsers are a skin over one of the iOS WebViews (always forget which one). Installing competing rendering engines is not allowed on iOS. That is sometimes bad, but in this particular case it’s good since it removes a major source of browser compatibility headaches.

Speaking of Chrome, in modern versions of this browser window.innerWidth/Height gives the dimensions of the layout viewport, and not the visual one. As I argued before this is a mistake, even though Chrome offers an alternative property pair.

Then the notch coordinates. Frankly, it was only during the writing of this article that I realised they do not use any known coordinate system. You might think they use the visual viewport coordinate system, and they kind of do, but it’s a weird, iOS-only variant.

The problem is that, only in Safari/iOS, screen.width/height always give the portrait dimensions of the ideal viewport. Thus, the zoom level of the actual, current landscape width is calculated relative to the ideal portrait width. That sounds weird but it doesn’t give any serious problems, because we use it throughout the script, and I (unconsciously) calculated the notch coordinates relative to this weird coordinate system as well.

Bottom line: this, again, would be a serious incompatibility headache in any cross-browser script, but because we’re only targeting Safari/iOS we don’t have any problems.

Still, I hope these two examples show that unilaterally changing the coordinate spaces of some viewport-related JavaScript properties is a bad idea. The situation is complicated enough as it is, and you never know what’s going to break.

A Boilerform Idea

Css Tricks - Tue, 10/03/2017 - 6:02am

This is just a random idea, but I can't stop it from swirling around in my head.

Whenever I need to style a form on a fresh project where the CSS and style guide stuff is just settling in, the temptation to reach for a mini form framework is strong. Form elements are finicky, have little cross-browser issues, and are sometimes downright hard to wrassle away styling control.

This idea, which I'm just now managing to write about, but haven't actually done any work toward, would be this mini-form framework. Maybe something like "Boilerform", as Dave jokingly suggested on an episode of ShopTalk.

I imagine it going something like this:

  • It would have basic form-styling to organize form elements, not unlike something like Foundation forms;
  • Account for cross browser issues, not unlike normalize.css;
  • Strong-arm styling control over form elements, not unlike WTF, forms?; and
  • Include native browser form validation stuff, including UX improvements via native JavaScript API's, not unlike Validate.js.

I think there is value in combining those things into one thing, but doing so with...

  1. A light touch, and without any more opinion about the final styling as possible, and with
  2. Flexibility, perhaps showing off a gallery of different form types with varied styling.

I probably don't have time to head up a project like this, but I wouldn't mind helping connect humans who also see value here and wanna give it a shot.

A Boilerform Idea is a post from CSS-Tricks

eBay’s Font Loading Strategy

Css Tricks - Tue, 10/03/2017 - 3:57am

Senthil Padmanabhan documents how:

  1. Both FOUT and FOIT are undesirable.
  2. The best solution to that is font-display.
  3. Since font-display isn't well supported, the path to get there is very complicated.
  4. They open sourced it.

They went with replicating font-display: optional, my favorite as well.

Direct Link to ArticlePermalink

eBay’s Font Loading Strategy is a post from CSS-Tricks

A Five Minutes Guide to Better Typography

Css Tricks - Mon, 10/02/2017 - 11:09am

Pierrick Calvez with, just maybe, a bunch of typographic advice that you've heard before. But this is presented very lovingly and humorously.

Repeating the basics with typography feels important in the same way repeating the basics of performance does. Gzip your stuff. Make your line length readable. Set far expires headers. Make sure you have hierarchy. Optimize your images. Align left.

Let's repeat this stuff until people actually do it.

Direct Link to ArticlePermalink

A Five Minutes Guide to Better Typography is a post from CSS-Tricks

Help Your Users `Save-Data`

Css Tricks - Mon, 10/02/2017 - 3:59am

The breadth and depth of knowledge to absorb in the web performance space is ridiculous. At a minimum, I'm discovering something new nearly every week. Case in point: The Save-Data header, which I discovered via a Google Developers article by Ilya Grigorik.

If you're looking for the tl;dr version of how Save-Data works, let me oblige you: If you opt into data savings on the Android version of Chrome (or the Data Saver extension on your desktop device), every request that Chrome sends to a server will contain a Save-Data header with a value of On. You can then act on this header to change your site's content delivery in such a way that conserves data for the user. This is a very open-ended sort of opportunity that you're being given, so let's explore a few ways that you could act on the Save-Data header to send less bytes down the wire!

Change your image delivery strategy

I don't know if you've noticed, but images are often the largest chunk of the total payload of any given page. So perhaps the most impactful step you can take with Save-Data is to change how images are delivered. What I settled on for my blog was to rewrite requests for high DPI images to low DPI images. When I serve image sets like this on my site, I do so using the <picture> element to serve WebP images with a JPEG or PNG fallback like so:

<picture> <source srcset="/img/george-and-susan-1x.webp 1x, /img/george-and-susan-2x.webp 2x"> <source srcset="/img/george-and-susan-1x.jpg 1x, /img/george-and-susan-2x.jpg 2x"> <img src="/img/george-and-susan-1x.jpg" alt="LET'S NOT GET CRAZY HERE" width="320" height="240"> </picture>

This solution is backed by tech that's baked into modern browsers. The <picture> element delivers the optimal image format according to a browser's capabilities, while srcset will help the browser decide what looks best for any given device's screen. Unfortunately, both <picture> and srcset lacks control over which image source to serve for users who want to save data. Nor should they! That's not the job of srcset or <picture>.

This is where Save-Data comes in handy. When users visit my site and send a Save-Data request header, I use mod_rewrite in Apache to serve low DPI images in lieu of high DPI ones:

RewriteCond %{HTTP:Save-Data} =on [NC] RewriteRule ^(.*)-2x.(png|jpe?g|webp)$ $1-1x.$2 [L]

If you're unfamiliar with mod_rewrite, the first line is a condition that checks if the Save-Data header is present and contains a value of on. The [NC] flag merely tells mod_rewrite to perform a case-insensitive match. If the condition is met, the RewriteRule looks for any requests for a PNG, JPEG or WebP asset ending in -2x (the high DPI version), and redirects such requests to an asset ending in -1x (the low DPI version).

Now comes the weird part: What happens if a user visits with Data Saver enabled, but turns it off and returns later on an unmetered (i.e., Wi-Fi) connection? Because we've surreptitiously rewritten the request for a -2x image to a -1x one, the browser will serve up the low quality version of the image from the browser cache rather than requesting the high quality version from the server. In this scenario, the user is lashed to a low quality experience until they empty their browser cache (or the cached entries expire).

So how do we fix this? The answer lies in the Vary response header. Vary instructs the browser how and if it should use a cached asset by aligning cache entries to specific header(s). Values for Vary are simply other header names (e.g., Accept-Encoding, User-Agent, et cetera). If we want the browser to cache content based on the existence of the Save-Data header, all we need to do is configure the server to send a Vary response header with a value of Save-Data like so:

<FilesMatch "\.(gif|png|jpe?g|webp)$"> Header set Vary "Save-Data" </FilesMatch> <FilesMatch "\.svg$"> Header set Vary "Accept-Encoding, Save-Data" </FilesMatch>

In this example, I'm sending a Vary response header with a value of Save-Data any time GIF, PNG, JPEG or WebP images are requested. In the case of SVGs, I send a Vary header with a value of Accept-Encoding, Save-Data. The reason for this is because SVGs are compressible text assets. Therefore, I want to ensure that the browser (and any intermediate cache, such as a CDN) takes the value of the Accept-Encoding header into consideration in addition to the Save-Data header when deciding how to retrieve entries from the cache.

Image delivery with Data Saver on vs. off

For our trouble, we now have an image delivery strategy that helps users conserve data, and will populate the browser cache with images that won't persist if the user turns off Data Saver later on.

Of course, there are other ways you could change your image delivery in the presence of Save-Data. For example, Cory Dowdy wrote a post detailing how he uses Save-Data to serve lower quality images. Save-Data gives you lots of room to devise an image delivery strategy that makes the best sense for your site or application.

Opt out of server pushes

Server push is good stuff if you're on HTTP/2 and can use it. It allows you send assets to the client before they ever know they need them. The problem with it, though, is it can be weirdly unpredictable in select scenarios. On my site, I use it to push CSS only, and this generally works well. Although, I do tailor my push strategy in Apache to avoid browsers that have issues with it (i.e., Safari) like so:

<If "%{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i"> Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style; nopush" </If> <Else> Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style" </Else>

In this instance, I'm saying "Hey, I want you to preemptively push my site's CSS to people, but only if they're not using Safari." Even if Safari users come by, they'll still get a preload resource hint (albeit with a nopush attribute to discourage my server from pushing anything).

Even so, it would behoove us to be extra cautious when it comes to pushing assets for users with Data Saver turned on. In the case of my blog, I decided I wouldn't push anything to anyone who had Data Saver enabled. To accomplish this, I made the following change to the initial <If> header:

<If "%{HTTP:Save-Data} == 'on' || %{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i">

This is the same as my initial configuration, but with an additional condition that says "Hey, if Save-Data is present and set to a value of on, don't be pushing that stylesheet. Just preload it instead." It might not be a big change, but it's one of those little things that could help visitors to avoid wasted data if a push was in vain for any reason.

Change how you deliver markup

With Save-Data, you could elect to change what parts of the document you deliver. This presents all sorts of opportunities, but before you can embark on this errand, you'll need to check for the Save-Data header in a back end language. In PHP, such a check might look something like this:

$saveData = (isset($_SERVER["HTTP_SAVE_DATA"]) && stristr($_SERVER["HTTP_SAVE_DATA"], "on") !== false) ? true : false;

On my blog, I use this $saveData boolean in various places to remove markup for images that aren't crucial to the content of a given page. For example, one of my articles has some animated GIFs and other humorous images that are funny little flourishes for users who don't mind them. But they are heavy, and not really necessary to communicate the central point of the article. I also remove the header illustration and a teeny tiny thumbnail of my book from the nav.

Image markup delivery with Data Saver on and off

From a payload perspective, this can certainly have a profound effect:

The potential effects of Data Saver on page payload

Another opportunity would be to use the aforementioned $saveData boolean to put a save-data class on the <html> element:

<html class="<?php if($saveData === true) : echo("save-data"); endif; ?>">

With this class, I could then write styles that could change what assets are used in background-image properties, or any CSS property that references external assets. For example:

/* Just a regular ol' background image */ body { background-image: url("/images/bg.png"); } /* A lower quality background image for users with Data Saver turned on */ .save-data body { background-image: url("/images/bg-lowsrc.png"); }

Markup isn't the only thing you could modify the delivery of. You could do the same for videos, or even do something as simple as delivering fewer search results per page. It's entirely up to you!


The Save-Data header gives you a great opportunity to lend a hand to users who are asking you to help them, well, save data. You could use URL rewriting to change media delivery, change how you deliver markup, or really just about anything that you could think of.

How will you help your users Save-Data? Leave a comment and let your ideas be heard!

Jeremy Wagner is the author of Web Performance in Action, available now from Manning Publications. Use promo code sswagner to save 42%.

Check him out on Twitter: @malchata

Help Your Users `Save-Data` is a post from CSS-Tricks

CSS font-variant tester

Css Tricks - Mon, 10/02/2017 - 3:58am

From small caps and ligatures to oldstyle and ordinal figures, the font-variant-* CSS properties give us much finer control over the OpenType features in our fonts. Chris Lewis has made a tool to help us see which of those font-variant features are supported in our browser of choice and I could definitely see this helpful for debugging in the future.

Direct Link to ArticlePermalink

CSS font-variant tester is a post from CSS-Tricks

safe-area-inset values on iOS11

QuirksBlog - Mon, 10/02/2017 - 2:12am

With the iPhone X’s notch came viewport-fit=cover and safe-area-inset, as explained here. It turns out that safe-area-inset is 0 on iOS11 devices that are not the iPhone X. This may sound logical, but I wonder if it is. Also, the value remains static, even when you zoom in.

Note: testing for this article was done exclusively on Apple’s simulator.

To recap briefly:

  • viewport-fit=cover, when added to the meta viewport, ensures the site takes over the entire screen, even the space below the notch, if applicable.
  • safe-area-inset-dir (where dir is left, right, top, or bottom) gives the safe areas you should apply if you want enough margin or padding to prevent your site from being obscured by the notch.

Let’s treat viewport-fit=cover first. When applied on the iPhone X, your sites now stretches into the space below the notch, as advertised. When applied on any other device with iOS11, nothing happens. That’s logical: the viewport is already stretched to its maximum and there is no notch to avoid or stretch under.

In other words, viewport-fit=cover can be added to any site and will fire only when applicable. Keep that in mind.

The safe area

safe-area-inset should be added as a padding (or, I suppose, a margin) to elements or the entire page. Its value on the iPhone X, in case you’re wondering, is 44px. This value could conceivably be different on future models where the notch is larger or smaller, so using a constant that may change from model to model is a good idea.

But what is its value on iOS11 devices that are not the iPhone X and have no notch? It turns out it’s 0px. This may sound logical as well, since there is no notch and thus no safe area, but is it?

My problem is the following. Suppose I have this:

element { padding-left: 10px; padding-left: constant(safe-area-inset-left); }

What I want to do here is give the element a padding-left of 10px, except when a notch is present, then I want to give it a pading-left equal to the safe area (44px). This works absolutely fine on the iPhone X and in non-iOS browsers. In the former the initial 10px values is overwritten by the safe area, while the latter don’t understand the safe area and ignore the second rule.

Problem is: on iOS11 devices other than the iPhone X this misfires and gives the element a padding-left of 0. Thus, safe-area-inset fires even when it’s not applicable. I do not find this logical at all. As far as I can see, safe-area-inset should simply be absent when there is no safe area to describe. And 0 is not the same as absent.

As far as I’m concerned Apple should remove safe-area-inset entirely from devices that do not need it. Thus we web developers do not need to worry about the notch. We write a tiny bit of CSS for the notch, and can rest assured that the CSS will not fire when it’s absent.

The official post notes that you should use the following instead, but also notes that max() is not supported by the current Safari/iOS version, which makes the advice a bit pointless:

element { padding-left: max(10px,constant(safe-area-inset-left)); }

So they kind-of admit there might be a problem, but offer an as-yet-unavailable solution. Also, as far as I’m concerned this tip-toes around the fundamental problem of having a safe area of 0 where none is needed.


There’s another problem as well: safe-area-inset is not adjusted when the user zooms, even though, at high zoom levels, the safe area becomes comically large. Even when I’m zoomed in to the maximum level on an iPhone X, the safe area is still 44px, though that now means about one-third of the screen.

I can understand why Apple did this. If safe-area-inset would become zoom-dependent, the browser would have to run re-layouts every time the user zooms, changing the calculated padding-left on every applicable element. This is likely to be a costly operation.

Still, the conclusion must be that safe-area-inset also misfires whenever the user zooms in.

Notch detection

So we have to write a notch detection script. Fortunately it’s quite simple: create a test element, apply the safe-area-inset and see if its value is larger than 0. If so, a notch is present.

function hasNotch() { if (CSS.supports('padding-left: constant(safe-area-inset-left)')) { var div = document.createElement('div'); = 'constant(safe-area-inset-left)'; document.body.appendChild(div); var calculatedPadding = parseInt(window.getComputedStyle(div).paddingLeft); document.body.removeChild(div); if (calculatedPadding > 0) { return true; } } return false; }

Still, I would argue that the very need for such a script means safe-area-inset has not been implemented quite properly.

Template Literals are Strictly Better Strings

Css Tricks - Sun, 10/01/2017 - 9:24am

Nicolás Bevacqua wrote this a year ago, and I'd say with a year behind us he's even more right. Template literals are always better. You don't have to screw around with concatenation. You don't have to screw around with escaping other quotes. You don't have to screw around with multiline. We should use them all the time, and adjust our linting to help us develop that muscle memory.

Besides the few things you can't use them for (e.g. JSON), there is also the matter of browser support. It's good, but no IE 11 for example. You're very likely preprocessing your JavaScript with Babel anyway, and if you're really smart, making two bundles.

Direct Link to ArticlePermalink

Template Literals are Strictly Better Strings is a post from CSS-Tricks

Turning Text into a Tweetstorm

Css Tricks - Fri, 09/29/2017 - 10:14am

With tongue firmly in cheek, I created this script to take a chunk of text and break it up into a tweetstorm, for "readability". Sort of like the opposite of something like Mercury Reader. If the irony is lost on you, it's a gentle ribbing of people who chose Twitter to publish long-form content, instead of, you know, readable paragraphs.

See the Pen Turning Text into a Tweetstorm by Chris Coyier (@chriscoyier) on CodePen.

It might be fun to look at how it works.

First, we need to bust up the text into an array of sentences.

We aren't going to do any fancy analysis of where the text is on the page, although is presumably some algorithmic way to do that. Let's just say we have:

<main id="text"> Many sentences in here. So many sentences. Probably dozens of them. </main>

Let's get our hands on that text, minus any HTML, like this:

let content = document.querySelector("#text").textContent;

Now we need to break that up into sentences. That could be as simple as splitting on periods, like content.split(". "), but that doesn't use any intelligence at all. For example, a sentence like "Where are you going, Mr. Anderson?" would be broken at the end of "Mr." and not at the "?", which ain't great.

This is find something on Stack Overflow territory!

This answer is pretty good. We'll do:

let contentArray = content.replace(?/([.?!])\s*(?=[A-Z])/g, "$1|").split("|");

I didn't bother to try and really dig into how it works, but at a glance, it looks like it deals with a few common sentence-ending punctuation types, and also those "Mr. Anderson" situations somehow.

We need some tweet templates.

There are two: the top one that kicks off the thread and reply tweets. We should literally make a template, because we'll need to loop over that reply tweet as many times as needed and that seems like way to go.

I reached for Handlebars, honestly because it's the first one I thought of. I probably could have gone for the ever-simpler Mustache, but whatever it's just a demo. I also couldda/shouldda gone with a template via Template Literals.

To make the template, the first thing I did was create a tweet with mock data in just HTML and CSS, like I was just devving out a component from scratch.

<div class="tweet"> <div class="user"> <img src="" alt="" class="user-avatar"> <div class="user-fullname">Jimmy Fiddlecakes</div> <div class="user-username">@everythingmatters</div> </div> <div class="tweet-text"> Blah blah blah important words. 1/80 </div> <time class="tweet-time"> 5:48 PM - 15 Sep 2017 </time> yadda yadda yadda

I wrote my own HTML and CSS, but used DevTools to poke at the real Twitter design and stole hex codes and font sizes and stuff as much as I could so it looked real.

To make those tweet chunks of HTML into actual templates, I wrapped them up in script tags how Handlebars does it:

yadda yadda yadda

Now I can:

// Turn the template into a function I can call to compile it: let mainTweetSource = document.querySelector("#main-tweet-template").innerText; let mainTweetTemplate = Handlebars.compile(mainTweetSource); // Compile it whenever: let mainTweetHtml = mainTweetTemplate(data);

The data there is the useful bit. Kind of the whole point of templates.

What is "data" in a template like this? Here's stuff:

Which we can represent in an object, just like Handlebars wants:

let mainTweetData = { "avatar": "200/", "user-fullname": "Jimmy Fiddlecakes", "user-username": "@everythingmatters", "tweet-text": "", // from our array! "tweet-time": "5:48 PM - 15 Sep 2017", "comments": contentArray.length + 1, "retweets": Math.floor(Math.random() * 100), "loves": Math.floor(Math.random() * 200), "tweet-number": 1, "tweet-total": contentArray.length }; Now we loop over our sentences and stitch together the templates. // .shift() off the first sentence and compile the main tweet template first let mainTweetHtml = mainTweetTemplate(mainTweetData); let allSubtweetsHTML = ""; // Loop over the rest of the sentences contentArray.forEach(function(sentence, i) { let subtweet_data = { // gather up the data fresh each time, randomzing numbers and // most importantly plopping in the new sentence: "tweet-text": sentence, ... }; let subTweetHtml = subTweetTemplate(subtweetData); allSubtweetsHTML += subTweetHtml; } // Now dump out all this HTML somewhere onto the page: document.querySelector("#content").innerHTML = ` <div class="all-tweets-container"> ${mainTweetHtml} ${allSubtweets} </div> `;

That should do it!

I'm sure there are lots of ways to improve this, so feel free to fork the Pen and have at it. Ultimate points would be to make it a browser extension.

Turning Text into a Tweetstorm is a post from CSS-Tricks

CSS Grid PlayGround

Css Tricks - Fri, 09/29/2017 - 4:13am

Really great work by the Mozilla gang. Curious, as they already have MDN for CSS Grid, which isn't only a straight reference, they have plenty of "guides". Not that I'm complaining, the design and learning flow of this are fantastic. And of course, I'm a fan of the "View on CodePen" links ;)

There are always lots of ways to learn something. I'm a huge fan of Rachel Andrew's totally free video series and our own guide. This also seems a bit more playground-like.

Direct Link to ArticlePermalink

CSS Grid PlayGround is a post from CSS-Tricks

iOS 11 Safari Feature Flags

Css Tricks - Fri, 09/29/2017 - 4:01am

I was rooting around in the settings for iOS Safari the other day and stumbled upon its "Experimental Features" which act just like feature flags in any other desktop browser. This is a new feature in iOS 11 and you can find it at:

Settings > Safari > Advanced > Experimental Features

Here's what it looks like today:

Right now you can toggle on really useful things like Link Preload, CSS Spring Animations and display: contents (which Rachel Andrew wrote about a while ago). All of which could very well come in handy if you want to test your work in iOS.

iOS 11 Safari Feature Flags is a post from CSS-Tricks

New fonts on Typekit from XYZ Type

Nice Web Type - Thu, 09/28/2017 - 10:22am

Meet our newest foundry partner, XYZ Type! Founded by Ben Kiel and Jesse Ragan, XYZ just launched this year and we are thrilled to offer their fonts here on Typekit.

Kiel and Ragan both have extensive experience as type designers, having worked at the likes of House Industries and Hoefler & Frere-Jones before going into independent work. Both have taught classes in type design as well — Kiel at Washington University, Ragan at Pratt, and both at Type@Cooper. We’re adding all three of their published families to Typekit Marketplace, and three styles will also be available in our subscription library for web and sync.

Aglet Slab, by Jesse Ragan, is a sturdy slab whose angular framework of 45- and 90-degree angles is matched by decidedly rounded corners and edges for an overall feeling of variety and an outgoing personality. With seven different weights and matching italics for each, Aglet is versatile and will suit a huge range of different projects. Aglet Slab Regular and Bold are both available in our library, and all other weights and styles are available for purchase through Typekit Marketplace.

Export, both Regular and Stencil

Also by Ragan, Export is another of XYZ Type’s founding typefaces, and its rather unconventional structures give this sans serif an unusually rugged appearance. The inspiration for this typeface came from printed letters on a cardboard box, spotted by Ragan in NYC Chinatown and reimagined for this all-caps design that he describes as having an “industrial rhythm.” The Stencil style is a lot of fun too — and don’t miss the extra shipping symbols. Both styles of Export are available on Typekit Marketplace.


Ben Kiel and Jesse Ragan both worked on the design for Cortado and released it at the end of 2014, and we’re delighted to offer the single style in our subscription library. Modeled after a hand-painted script from illustrator Cecilia Carlstedt, Cortado is filled with fresh energy, but comes off as relaxed — it’s a great choice for anything that needs a bit of a midcentury feel.

See the whole collection from XYZ Type on their foundry page, and let us know what you think! We’d love to hear where you use these. Keep an eye on our Twitter and Instagram feeds for news about new type in our library.

A Poll About Pattern Libraries and Hiring

Css Tricks - Thu, 09/28/2017 - 5:41am

I was asked (by this fella on Twitter) a question about design patterns. It has an interesting twist though, related to hiring, which I hope makes for a good poll.

Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.

I'll let this run for a week or two. Then (probably) instead of writing a new post with the results, I'll update this one with the results. Feel free to comment with the reasoning for your vote.


At the time of this update (September 2017), the poll has been up for about 6 weeks.

61% of folks said they would be more likely to want a job somewhere that were actively using (or working toward) a pattern library.

That's a strong number I'd say! Especially when 32% of folks responded that they don't care. So for 93% of folks, they either are incentivized to work for you because of a pattern library or don't mind. So is a pattern library good not only for your codebase and business, for attracting talent as well.

Only 7% of folks would be less likely to want to work there. Presumably, that's either because they enjoy that kind of work and it's already done, or find it limiting.

Read the comments below for some interesting further thoughts.

A Poll About Pattern Libraries and Hiring is a post from CSS-Tricks

?HelloSign API: The dev friendly eSign

Css Tricks - Thu, 09/28/2017 - 5:40am

(This is a sponsored post.)

We know that no API can write your code for you (unfortunately), but ours comes close. With in-depth documentation, customizable features, and dashboard that makes your code easy to debug, you won't find an eSignature product with an easier path to implementation. 2x faster than other esignature APIs.

“We wanted an API built by a team that valued user experience as much as we do. At the end of the day, we chose HelloSign because it was the best combination of these features, price and user experience.”??- Max Mullen Co-Founder of Instacart

Test drive HelloSign API for free today.

Direct Link to ArticlePermalink

?HelloSign API: The dev friendly eSign is a post from CSS-Tricks


Css Tricks - Thu, 09/28/2017 - 5:33am

As of WordPress 4.7 (December 2016), WordPress has shipped with a JSON API built right in. Wanna see? Hit up this URL right here on CSS-Tricks. There is loads of docs for it.

That JSON API can be used for all sorts of things. I think APIs are often thought about in terms of using externally, like making the data available to some other website. But it's equally interesting to think about digesting that API right on the site itself. That's how so many websites are built these days away, with "Moden JavaScript" and all.

So it's possible to build a WordPress theme that uses it's own API for all the data, making an entirely client-rendered site.

I would have thought there would be a bunch of themes like this available, but it seems it's still new enough of a concept there isn't that many. That I found, anyway. I did find Foxhound though, by Kelly Dwan. It's simple and quite nice looking:

It's React-based, so the whole thing is logically busted up into components:

I popped it up onto a test site and it works pretty good! So that I could click around and do various stuff, I imported the "theme test unit" data, which is a nice and quick way of populating a fresh WordPress install with a bunch of typical stuff (posts, authors, comments, etc) for testing purposes.

Only a shell of a page is server-rendered, it looks like. So without JavaScript at all, you get nothing. Certainly, you could make all this work the regular server-rendred WordPress way, you'd just be duplicating a heck of a lot of work, so it's not surprising that isn't done here. I would think it's more likely you'd try to server-render the React than keep the PHP stuff and React stuff in sync.

About 50% of the URL's you click load instantly, like you'd expect in an SPA type of site. Looks like any of the links generated in that shell page that PHP renders do a refresh, and links that are rendered in React components load SPA style.

I would think this would be a really strong base to start with if you were interested in building a React-powered WordPress site. That's certainly a thing these days. I just happened to be looking at the Human Made site, and they say they did just that for ustwo:

ustwo wanted to build a decoupled website with a WordPress backend and a React frontend. Human Made joined the development team to build the WordPress component, including custom post types and a custom REST API to deliver structured data for frontend display.

So ya know, people are paying for this kind of work these days.

Foxhound is a post from CSS-Tricks

How Different CMS’s Handle Content Blocks

Css Tricks - Wed, 09/27/2017 - 5:48am

Imagine a very simple blog. Blog posts are just a title and a paragraph or three. In that case, having a CMS where you enter the title and those paragraphs and hit publish is perfect. Perhaps some metadata like the date and author come along for the ride. I'm gonna stick my neck out here and say that title-and-content fields only is a CMS anti-pattern. It's powerful in its flexibility but causes long-term pain in lack of control through abstraction.

Let's not have a conversation about CMS's as a whole though, let's scope this down to just that content area issue.

Now imagine we have a site with a bit more variety. We're trying to use our CMS to build all sorts of pages. Perhaps some of it is bloggish. Some of it more like landing pages. These pages are constructed from chunks of text but also different components. Maps! Sliders! Advertising! Pull quotes!

Here are four different examples, so you can see exactly what I mean:

I bet that kind of thing looks familiar.

You can absolutely pull this off by putting all those blocks into a single content field. Hey, it's just HTML! Put the HTML you need for all these blocks right into that content field and it'll do what you want.

There's a couple of significant problems with this:

  1. Not everyone is super handy with HTML. You might be setting up a CMS for other people to use who are great with content but not so much with code. Even for those folks who are comfortable with HTML, this doesn't leverage the CMS very well. It would be a lot easier, for example, to rearrange a page by dragging and dropping then it could carefully copy and pasting HTML.
  2. The HTML-in-the-database issue. So you have five pages with an image slider. The slider requires some specific, nested, structured HTML. Are you dropping that into five different pages? That slider is bound to change, and you'll want to avoid changing it five times. Keep your HTML in templates, and data in databases.

So... what do we do? I wasn't really sure how CMS's were handling this, to be honest. So I looked around. This is what I've found.

In CraftCMS...

CraftCMS has a Matrix field type for this.

A single Matrix field can have as many types of blocks as needed, which the author can pick and choose from when adding new content. Each block type gets its own set of fields.

In Perch...

Perch handles this with what they call Blocks:

In our blog template, the body of the post is just one big area to add text. Your editor, however, might want to build up a post with images, or video, or anything else. We can give them the ability to choose between different things to put into their post using Perch Blocks.

In Statamic...

Statamic deals with this idea with Replicator meta fieldtype:

The Replicator is a meta fieldtype giving you the ability to define sets of fields that you can dynamically piece together in whatever order and arrangement you imagine.

In WordPress...

It's tempting to just shout out Advanced Custom Fields here, which seems right up this alley. I love ACF, but I don't think it's quite the same here. While you can create new custom fields to use, it's then on you to ask for that data and output it in templates in a special way. It's not a way of handling the existing content blocks.

Something like SiteOrigin Page Builder, which works by using the existing content area and widgets:

There is also the forthcoming Gutenberg editor. It's destined for WordPress core, but for now it's a plugin. Brian Jackson has a good article covering it. In the demo content of Gutenberg itself it explains it well:

The goal of this new editor is to make adding rich content to WordPress simple and enjoyable. This whole post is composed of pieces of content - somewhat similar to LEGO bricks - that you can move around an interact with. Move your cursor around and you'll notice differnet blocks light up with outlines and arrows. Press the arrows to reposition blocks quickly, whichout fearing about losing things in the process of copying and pasting.

Note the different blocks available:

In Drupal...

Drupal has a module called Paragraphs for this:

Instead of putting all their content in one WYSIWYG body field including images and videos, end-users can now choose on-the-fly between pre-defined Paragraph Types independent from one another. Paragraph Types can be anything you want from a simple text block or image to a complex and configurable slideshow.

In ModX...

ModX has a paid add-on called ContentBlocks for this:

The Modular Content principle means that you break up your content into smaller pieces of content, that can be used or parsed separately. So instead of a single blob of content, you may set a headline, an image and a text description.

Each of those small blocks of content have their own template so you can do amazing things with their values.

Of course those aren't the only CMS's on the block. How does yours handle it?

How Different CMS’s Handle Content Blocks is a post from CSS-Tricks

Syndicate content
©2003 - Present Akamai Design & Development.