Article Archives

CSS Property Usage > Popularity

And the most-used CSS property is... (guess before you click through).

There are some funny ones at the bottom. Hopeful ones like kerning and not-enough-coffee ones like text-underline.

A Complete Guide to the Table Element

The <table></table> element in HTML is used for displaying tabular data. You can think of it as a way to describe and display data that would make sense in spreadsheet software. Essentially: columns and rows. In this article we're going to look at how to use them, when to use them, and everything else you need to know.

(more…)

Controlling CSS Animations and Transitions with JavaScript

The following is a guest post by Zach Saucier. Zach wrote to me telling me that, as a frequenter on coding forums like Stack Overflow, he sees the questions come up all the time about controlling CSS animations with JavaScript, and proved it with a bunch of links. I've had this on my list to write about for way too long, so I was happy to let Zach dig into it and write up this comprehensive tutorial.

(more…)

Responsive Elements

Width based media queries are based on the entire browser window. If the browser window is narrower than 800px, do this. If the browser is window is wider than 400px, do this. But that's not always enough. Imagine a desktop 3-column layout at 1000px. Each column is 333px wide. Then you have a media query break at 800px which drops it to a 2-column layout, and with the third below. Even though the browser is now narrower, each column is wider (400px). It would be easier to write media queries for the modules inside those columns based on the current width of the column, not the browser window.

Kumail Hunaid's project can help with that. I like the approach. It adds class names to elements that you then use to style, so it's pretty unobtrusive.

Client-side full-text search in CSS

Clever idea by François Zaninotto. Add to the searchable element a data-index attribute which contains all the text content of its children smooshed together. Then you can find matches using the [data-index*=""] selector, which is fast. Essentially doubles the DOM weight, but that's rarely too big of a deal.

The Parallels Between Personal Health and Website Health

I recently spent a week at Hilton Head Health, a weight loss spa in South Carolina. Part of the experience was classroom learning about lots of different health related topics. While hearing all about those things, I couldn't help but think about parallels between personal health and the health of websites. Mostly about web performance. Perhaps looking at these similarities is useful, as there is great value in taking care of both and sometimes a good ol' analogy can trigger understanding and action.

(more…)

BeeLine Reader

An attempt to make reading on screens easier though applying color gradients to lines of text. For example, one line of text will fade to red and the next line will start with red, making it easier for your eye to jump down to the right place. It looks silly, but I've tried it a few times now and it does seem to make me read faster and more comfortably.

I'm not sure why it has to be all "All rights reserved" / "patent pending" yadda yadda. I would think it would help the world more if the idea was open and the company made money through good implementations of the idea (e.g. paid app components).

WordPress Fragment Caching Revisited

The following is a guest post by Ryan Burnette. As you'll read below, Ryan was working on a WordPress site that utilized a plugin that used the Instagram API to pull down photos. He was using it in a bit of a non-standard way that lead to lots of requests and a very slow site. In poking around at different solutions, he came across fragment caching. But unfortunately some of the information he found was outdated, so, like a good developer, he updated it. Here's the backstory and journey.

(more…)

The HTML5 progress Element

The following is a guest post by Pankaj Parashar. Pankaj wrote to me about some pretty cool styled progress elements he created. I asked if he'd be interested in fleshing out the idea into an article about styling them in general. Thankfully, he obliged with this great article about using them in HTML, styling them with CSS as best as you can cross-browser, and fallbacks.

(more…)

CSS Animate from/to “auto”

I have no doubt CSS will allow this one day, but right now, you can't animate the width or height of an element from a fixed value to auto. This is particularly useful when the desire is to animate from hidden to visible like jQuery's slideDown(). Nikita Vasilyev shows how you can do it with a touch of JS, but still using CSS for the actual animation/transition.

The more difficult one is to auto: 1) measure width 2) set auto 3) measure again 4) set back to previous 5) force repaint 6) apply transition 7) change width to measured auto value 8) set to auto for real. #wipesbrow

And yeah there is the max-height/width technique, but I'm not a fan. It messes with the transition timings and requires magic numbers.

Tridiv

A web app by Julian Garnier for building and manipulating 3D shape creations in CSS. The interface is genius. One panel shows you the creation from an angle so you can see the 3D-ness of it and spin it around. The other three panes show you the creation from different straight on angles so you can drag them around in the relevant directions.

Check out a demo if you aren't impressed yet.

In the Preview Mode there is a button where you can one-click move it over to CodePen. How 'bout that?

Website Critique: epicawesome.co

Back when I did the Kickstarter for this site, one of the rewards I offered was a critique, public or private, of any website. The only taker was Gus Fune, who opted for the public critique of a site he worked on: epicawesome.co. Thank you Gus for allowing this to be a public learning opportunity!

(more…)

Above-The-Fold CSS

What is the most important CSS on the page? The styles that affect what you can see immediately. Chances are, that is far less CSS than your entire stylesheet(s). What if you could serve just that CSS right away rather than your entire (blocking) stylesheet? Paul Kinlan shares an idea.

Let’s <cite> People

Bruce Lawson:

Once again, I propose that the definition of <cite> be reverted to include the real-world use for marking up names of those cited, and that the spec note that cite-inside-blockquote is one way (although not the only way) to link a quotation with the work or the person being quoted.

+1

The cowpath was already paved, so we just need to stomp it down again.

Job Titles in the Web Industry

There are loads of job titles in our industry. The opinion on their usefulness range from harmful (i.e. leads to “not my job” syndrome) to vital (i.e. people change companies sometimes and need common language). Since they are out there and we use them, there should be some consistency to their definition. Perhaps we can get closer to nailing that down.

Let's light this fire, shall we? This is all debatable, of course.

(more…)

Don’t Swear in Your Stylesheets

Aimee Ault from deviantART discovered that some of their stylesheets would fail to load for some users. Turns out those users were

accessing the site from computers with overly sensitive system-wide profanity filters installed. These users' browsers likely stopped parsing the stylesheet entirely upon reaching the word in the stylesheet, leading to a fairly ugly and/or broken page.

Ideally you have a build system that compresses CSS and removes comments, but if for whatever reason you ship CSS with comments in it, don't swear.

SVG Filters on Text

The following is a guest post by Chris Scott. Chris was messing around with SVG filters and how they can be applied to text. I thought this was quite interesting because SVG filters are quite a bit different than CSS filters. Arguably more powerful, as there are more of them and you can do things like bevel/emboss or stroke which you can't in CSS filters. Chris goes into detail here on how it's done including a tool to make it even easier.

There has been a general trend in Web development, for some years now, away from using images in designs. Only a few years ago software companies would favour using an image of a rounded corner as the best "cross-browser" solution; the CSS attribute border-radius has made that technique seem very antiquated today. Titles are another example of this trend, where in the past one may have generated a fancy banner title in Photoshop and used an image to show it on the page. These days we have web fonts at our disposal and CSS3 to help us achieve shadows and other effects. These solutions load much faster, scale better and are more accessible and semantically correct. But there is even more we can do!

SVG Filters

SVG with Filter Effects have a lot of potential for complex text styling. Take a look at this example:

See the Pen SVG Filters on Text by chrismichaelscott (@chrismichaelscott) on CodePen

That line is created using SVG Filter Effects. It's just text. You can select it with your cursor. Search engines can index it. It will scale in size without losing quality. To boot, it takes very little time to download. You can achieve a whole lot more, too, the scope for creativity with Filter Effects is huge. The example was created with a library called Raphael.js and an extension I wrote for it. This article talks about the rationale for developing the extension and shows - in brief - how it can be used.

Apparently, only 0.1% of Web pages use SVG graphics. If that statistic is anything to go by, there's a good chance that you are probably not using SVG on a regular basis. Why is SVG used so unpopular? It's only a guess, but the reason I didn't get into SVG (until I absolutely had to) was its learning curve: SVG is an XML vocabulary and is, I think, extremely technical (matrix multiplication for colour shifts, anyone?). The way I got into SVG was through Raphael.js, a JavaScript Library for creating vector drawings. Because it's a JavaScript library it felt fairly familiar, all of the complexity was abstracted away. Before long I was creating complex graphics like a pro.

Filter Effects for Raphael

Raphael has a shortcoming though: no support for Filter Effects. I remember one of my customers specifically requesting a drop shadow for bubbles in a data visualization which was interactive and animated. The request stumped me for a while as I bumped into this limit of Raphael. For that project I wrote a very specific extension to Raphael for handling drop shadows. But the same complexity that had initially put me off SVG was back and worse than ever. Make no mistake, Filter Effects are very, very technical.

So, after that project, I set about building a more full-featured library to make Filter Effects as easy to apply as Raphael makes drawing shapes.

Introducing Filter Effects for Raphael!

Here's how to use it:

First, the HTML. This bit is dead simple, just a div with an id:

<div id="title-container"></div>

Everything else is done in JavaScript.

To start an SVG drawing with Raphael you create a "paper" by referencing the id of the container element:

var paper = Raphael("title-container");

Now to do some drawing. This example creates some text and sets some of the style attributes:

// The first two arguments are the origin of the text
var title = paper.text(0, 30, "Filters are ice cold");
title.attr({
"fill": "MintCream",
"font-family": "Butcherman",
"font-size": "54px",
"text-anchor": "start"
});

Now for some effects! The simplest things you can do are shadows, blurring, lighting, embossing and colour shifting. Those require very little coding. Let's try the emboss effect. Add to the JavaScript:

title.emboss();

You can chain effects, so applying a shadow afterwards is straightforward:

title.emboss().shadow();

Pretty cool, huh? You can take this much further if you want, by creating your own filters. The SVG spec lists (lower level) filter effects which can be combined to create all kinds of filters (convulsion matrices, in particular, can be used for a vast number of operations).

This demo has the full code and some other examples of different effects that can be achieved:

See the Pen SVG Filters on Text by chrismichaelscott (@chrismichaelscott) on CodePen

Shortcomings

What are the downsides to SVG? Well - aside from the pros and cons of vector over raster (like canvas) - there are a couple I can think of:

  • Browser support - You may not be surprised to learn that the graphical trickery discussed here is not supported in older versions of IE, 10 only. SVG itself will render in IE9, just without the effects. Firefox, Chrome and Opera have supported Filter Effects for ages
  • Semantics - Some may have reservations about the semantic validity of using SVG in documents, certainly the svg tag doesn't give any clue as to it's content; you can use a sensible parent, though

Wrapping Up

Hopefully this piece has given you a good idea of what filter effects can do and how Filter Effects for Raphael can do them. Check out the project page on Github for more details. Thanks for reading!

Emmet LiveStyle

You might have seen a workflow where you can save out of DevTools to file. But have you seen it changes made in DevTools instantly update the code in your editor in real time? And vice versa?

Creating a 3D Cube Image Gallery

The following is a guest post by Kushagra Gour (@chinchang457). Kushagra wrote to me to show me a fun interactive demo he made. It touches on many of the concepts of 3D transforms in CSS, a topic we haven't covered a ton here. So here's Kushagra taking the reins to explain these concepts through a demo.

(more…)

Spacing The Bottom of Modules

Ah the humble module! A good many designs these days make use of modules in the content-y and app-y sites alike. A chunk of information, an advertisement, a grouped set of functionality... could be anything. The fact that they likely have visual similarity yet can contain anything leads to an interesting CSS challenge: how do you pad the inside consistently?

(more…)

“an oddly reductive position to hold.”

[Pitchfork Holding Web Designer #1]: All designers should learn to code!
[Pitchfork Holding Web Designer #2]: No! Worrying about implementation influences design for the worse!
[Josh Seiden]: wtf.

Most designers are comfortable starting with bad ideas and iterating until they find satisfying solutions. Along the way, we throw out lots of ideas, for lots of reasons. We should be mature enough to throw out ideas that are unduly influenced by the system model.

The “Other” Interface

I like this sentiment by Robin Rendle:

As front-end developers and designers, we’re constantly refining two interfaces simultaneously: one for visitors who load the website, the other for developers who have to tackle the code in the future

Surprise! Preprocessors give you the organizational tools to do a good job with this.

Making Websites for Geezers

The following is a guest post by Michael Buchmiller and Mark Kearns. Last time we had Michael on, he wrote about executing a crazy idea he had to use decoder glasses on the web. Now now Michael is back with Mark (Hand Carved Graphics) to share some more fun ideas from a recent project they worked on.

Let me start off by saying that if you are looking for practical applications of CSS that could apply to any website and improve usability, this isn’t the article for you. If you are looking for creative implementations of code for comedic effect, and possibly inspiration for your next ridiculous project, then welcome.

We recently worked on a website for the cover band Geezer (www.getoffofmylawn.com). And yes, it's a bunch of guys that dress up as old men, pass out Werther's Originals candies, and rock the mike while playing covers and mash ups of songs by Weezer, Beastie Boys, and a host of others. I'm not generally a fan of cover bands, but what they do transcends the genre, and for them I make an exception.

Sure, they needed a website to post their concerts and news on, but more than that, they wanted something that reflected their brand of humor and captured the spirit of the band. They wanted something over the top. And that's what they got. Aside from the general turn-of-the-century aesthetics, there were three features in particular of note that we’ll be covering here:

  1. "Click to View in Large Print"
  2. Their tumbling Tumblr link
  3. (My personal favorite...) a page of blurry text dubbed "Geezer-Vision"

Click to View in Large Print

You know how some websites allow visitors to control the size of the body's HTML text for better usability? That's not what this is. Instead, clicking on the link blows the body copy wildly out of proportion for comedic effect.

It was achieved using jQuery onclick listeners that change the element's class and inline CSS properties.

$(".click-large-print, .decreaseFont").click(function() {
  var type= $(this).val();
  var curFontSize = $('.content').css('font-size');

  if ($(this).hasClass('click-large-print')) {
    $('.content').css('font-size', '2.8em');
    $('#click-large-print').text('Click to view in small print')
    $('#click-large-print').removeClass('click-large-print')
    $('#click-large-print').toggleClass('click-small-print')
  } else {
    $('.content').css('font-size', '0.8em');
    $('#click-large-print').text('Click to view in large print')
    $('#click-large-print').toggleClass('click-large-print')
  }

});

The 'click-large-print' and 'click-small-print' classes are empty and only serve as identifiers for jQuery.

Not an earth-shattering idea or implementation, but it's good for a laugh. Plus we're just getting warmed up.

I'VE TUMBLD AND I CAN'T GET UP

If you watched television at some point in the last 30 years, there's a good chance you are familiar with the ubiquitous medical alert services commercials targeting senior citizens and Mrs. Fletcher's catch phrase, "I've fallen and I can't get up." If somehow you are not, it wouldn't hurt to take a quick peek at the classic commercial.

The campy re-enactments combined with the unimaginable volume of airtime it consumed seared the slogan in to our collective memory.

There was never a question of if we'd try to work this in to the site somehow, but rather how would we do it. We discussed having a photo of a senior citizen that fell over on a hover state, but that seemed too expected. So instead we mashed up the idea with a link for the aptly named Tumblr. When you click on the Tumblr icon, the entire site rotates 90 degrees using CSS Transform properties and "falls" over. There's a slight delay before the visitor is redirected to the band's Tumblr page entitled "I’ve Tumbld and I Can’t Get Up."

var tumblrbutton = document.getElementById('tumblr-button');
  tumblrbutton.addEventListener('click', function() {

  // Apply the "rotate" class to the body
  $("body").toggleClass("rotate");

  // This delays opening the Tumblr link for 1.5 seconds
  setTimeout(function() {
    window.location.href = "http://www.username.tumblr.com";
  }, 1500); 

}, false);
body {
  -moz-transition: all 1s ease;
  -webkit-transition: all 1s ease;
  -o-transition: all 1s ease;
  transition: all 1s ease;
}

body.rotate {
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  transform: rotate(90deg);
}

The code to make a site rotate isn't anything new, but this is the first time I've found a worthwhile reason to use it. To make sure the icon didn't go unnoticed, we added a little animation to the GIF to draw some attention.

As a side note, yes the band has sent this link to the folks at Tumblr, and yes, they did think it was hilarious.

HAND ME MY READING GLASSES, SONNY

A while back I wrote an article for CSS-Tricks.com explaining how I'd re-appropriated AnythingZoomer to work as a set of retro decoder glasses rather than as a way to zoom in on a photo. As we were working on the Geezer website, that was still kicking around in the back of my mind. The concept for it this time around was to have the History page filled with blurry text, and visitors would have to use virtual reading glasses to make any of it out.

See it in action at http://getoffofmylawn.com/pages/history.

Blurry Text

The first step was to figure out how to make HTML text appear blurry. This was accomplished with a CSS Text Shadow, but instead of making the shadow black and offset, it is a color very close to the text color and directly behind it, giving it a sort of glow.

.small p.active {
  color: #bca47f;
  text-shadow: 0 0 6px #4d250f;
}

Is my eyesight going? It's getting more and more blurry.

We got that working, but as we were playing with it, we thought... you know what would make this funnier? If the text slowly got more and more blurry as you were on the page. Cruel and Kaufman-esque? Undoubtedly. But for Geezer's target audience, we thought they would appreciate the gag. We pulled this off with more CSS Transform properties triggered by jQuery.

// Change the class to the final blur state to initiate the transition
$(".small p").toggleClass("active");
./* Default class pre-blur within CSS transition properties */
.small p { 
  -webkit-transition:color 9s ease-in, text-shadow 9s ease-in;
  -moz-transition:color 9s ease-in, text-shadow 9s ease-in;
  -o-transition:color 9s ease-in, text-shadow 9s ease-in;
  -ms-transition:color 9s ease-in, text-shadow 9s ease-in;
  transition:color 9s ease-in, text-shadow 9s ease-in; 
  font-size: 16px;
  width: 630px;
  color: #af9572;
  text-shadow: 0 0 1px #4d250f;
}

/* Final class with full blur */
.small p.active {
  color: #bca47f;
  text-shadow: 0 0 6px #4d250f;
}

Tying It All Together with AnythingZoomer

Now that the text is completely unreadable, we used AnythingZoomer to act as a pair of reading glasses and reveal the crisp version of the text. It is designed to transform small text with magnified, large text as you hover over it, and works with both images (like the decoder glasses project) and HTML text. Instead of going from small to large, here we are going from blurry to crisp.

<script src="/js/jquery.anythingzoomer.min.js"></script>
<script> 
  var zoomertimer;
  $(document).ready(function() {

    // timer to delay the start of the blur effect
    setTimeout(function() {
      $(".small p").toggleClass("active");
    }, 10000);

    // timer and function to delay anythingZoomer from cloning the zoom area BEFORE the full blur is reached but allow for mouse-over override
    zoomertimer = setTimeout(function() { zoomer(); }, 24000);
    $(document).one('mouseenter mouseleave', "#zoom", function() { 
      if (zoomertimer) {
        zoomer();
        clearTimeout(zoomertimer);
        zoomertimer = null;
      }
    });
  });

  function zoomer() { 
    $("#zoom").anythingZoomer({
      clone: true
    }); 
  }
</script>
/* Default class pre-blur within CSS transition properties */
.small p { 
  -webkit-transition: color 9s ease-in, text-shadow 9s ease-in;
  -moz-transition: color 9s ease-in, text-shadow 9s ease-in;
  -o-transition: color 9s ease-in, text-shadow 9s ease-in;
  -ms-transition: color 9s ease-in, text-shadow 9s ease-in;
  transition: color 9s ease-in, text-shadow 9s ease-in; 
  font-size: 16px;
  width: 630px;
  color: #af9572;
  text-shadow: 0 0 1px #4d250f;
}

/* Final class with full blur */
.small p.active {
  color: #bca47f;
  text-shadow: 0 0 6px #4d250f;
}
.zoom { display: block; margin: 0 auto; }
.large p { font-size: 16px; width: 630px; }
.large { margin-top: 75px; margin-left: 175px; }

We are already testing visitors' patience with this page as is, so we made sure that this instance of AnythingZoomer spanned the width of our content to make it easy to just scan down the page without having to weave too much back and forth with the mouse to decipher the text.

Other Implementation Ideas

Don't have a project where you need to make it easy to read intentionally blurry text? Who does? But all is not lost. If you take the concept and apply it in different ways, you might be able to find some other fun applications.

Archeologists, You Dig?

What if instead of the text initially being blurry, the copy was rendered in a foreign font? You could have users translating ancient Egyptian text just by hovering over it.

Conspiracy Theorists Unite

If the initial text state was set to be the same color as the background of the page, it could be invisible until you hover over it to reveal a secret message.

Thanks for reading about how we made a website for Geezers!

Website Deployment: Let Us Count The Ways!

Deployment is moving a website from a local environment to live servers. What seems like a simple thing can actually be quite complex. There are absolutely loads of ways to go about it. They range from user friendly software and services, to more complex command line tools, to full blown systems with lots of moving parts.

I'm not an expert in all this, but I've set up a few different deployment systems in my day as well as worked with a number of different ones. I thought we could try and round up and break down as much as we can here.

(more…)

The East Wing, Part 2

I got to be a guest on Tim Smith's The East Wing podcast. I talk about some of the stuff that's happened in my life since the last time I was on the show over a year ago, like the Kickstarter and CodePen. We also get into some random topics like freelancing and frameworks.

How Web Tech Concerns Change

As a beginner in any specific web tech, your first concern is "what is this and how does it work?" As you level up, those concerns change. You may still learn about about how it works as you dive deeper, but other concerns will emerge the more you know, the more you use it, and the more work of others you are exposed to.

(more…)

Sass + Dev Tools Workflow

There have been a couple of good articles lately on improving the Sass/CSS workflow by using 1) Source Maps so Chrome knows what's up with your Sass files and partials 2) Telling Dev Tools to save changes back to disk 3) Ensuring those changes get automatically re-compiled 4) Using the LiveReload browser extension to ensure those changes are injected onto the page.

Ben Frain's Faster Sass debugging and style iteration with source maps, Chrome Web Developer Tools and Grunt and Tim Lucas' Getting started with CSS sourcemaps and in-browser Sass editing.

Source Maps requires Sass 3.3 which is in Alpha and and doesn't work with Compass yet.

If Kerouac wrote JavaScript

When I opened Johnson’s completed assignment, I found a short note from the good doctor, explaining why he had chosen to use CoffeeScript: “Sir, the funcktion key-word is an ALBATROSS and the curly brace is worthless FILIGREE. I desire a clean and artickulate script for the dockumenting of my varied MUSINGS”.

The Almanac is “Complete”

This is just a note to let ya'll know The Almanac section on CSS-Tricks is complete. Not complete as in totally done and never will be changed or anything foolish like that, but complete as in all CSS selectors and CSS properties are present and have complete informational pages about them.

It took a while! I wrote a good number of them, but then pulled in help to get it all completed. Big thanks to: Louis Lazaris, Estelle Weyl, Zachary Kain, Dennis Gaebel, Hugo Giraudel, Timothy Miller, Jared Stephens, Chris Burton, Rob Simpson, and Sacha Schmid for helping out (sorry if I missed anyone there!).

I already have several big ideas to make it better, so we'll just keep trucking along there. If you see something incorrect in there, just leave a comment. I'll see it and fix it.

Create Striped Backgrounds With Gradients (and a Sass Mixin)

The following is a guest post by Hugo Giraudel. Hugo has written several times for CSS-Tricks including an article about a rather clever Pie Timer and several entries for the Almanac. I'm glad to have him back, this time explaining some pretty hardcore Sass stuff with a really practical application.

Hey guys! I'm glad to be able to write for CSS-Tricks again and share some cool tricks about Sass! In the past few weeks, I've been intensively experimenting with Sass lists. I have found a lot of things that likely most people don't know.

I recently built a @mixin to create stripes. The idea is to give the mixin a regular gradient and it will turn it into a striped one. Since it turned out to be a fairly complicated thing to do, I thought it could be a good idea to write up.

Let's begin with some reminders about how gradients work.

Striped Gradients

When you give a gradient two succesive color-stops with the same stop value, the transition between them two is abrupt instead of smooth. It is technically a gradient, but there is no smooth transition from one color to another. Consider the following code:

.el {
  /* This is smooth */
  background: linear-gradient(deepskyblue, tomato);

  /* This is striped */
  background: linear-gradient(deepskyblue 50%, tomato 50%);
}
Check out this Pen!

You may put as many color-stops as you want as long as you remember to give each color-stop the same stop-value as the previous one (except for the first).

.french-flag {
  height: 10em;
  width: 15em;
  background: linear-gradient(
    to right, 
    blue 33.33%, white 33.33%, 
    white 66.66%, red 66.66%
  );
}
Check out this Pen!

That's pretty much everything you need to know about gradients for this article. If you ever happen to be interested in digging deep into the gradients, Ana Tudor wrote a wonderful article about this.

Sass Lists

Let's take this from the very start. Lists in Sass are quite similar to arrays in JavaScript. To initialize a list: $list: ();.

Note you can also initialize it with $list: null; (or even $list: unquote("");) if you feel like it, but beware they are different. Anyway, here is a very simple Sass list:

$css-tricks-is: (#b4d455, 42, "awesome");

This gets a bit more complex, because the Sass syntax is very permissive when it comes to lists. You can do a ton of things, some of which you're not supposed to. Let's take them one by one.

You can ommit braces.

You are not forced to wrap your lists with braces and can totally ommit them if you feel like it. We often ommit them to be honest.

$css-tricks-is: #b4d455, 42, "awesome";

The first index is 1

Not 0 like arrays. This is unfortunate since it makes our upcoming example code more complicated. This is an important thing to know when you're manipulating indexes with the nth() function.

$item-1: nth($css-tricks-is, 1); // #b4d455

You can separate values with spaces or commas.

Both are perfectly valid. I'm pretty sure you'll prefer commas since it's the standard separator for array values (JS, PHP...) but you can totally use spaces if you feel like it.

$css-tricks-is: #b4d455 42 "awesome";

You can mix spaces and commas.

You can have the first-level list comma-separated and the nested one space separated in nested lists. In the following example, the 3rd value is a space-separated list.

$css-tricks-is: #b4d455, 42, "awesome" "interesting" "free";

You can ommit quotes around strings.

That's right, strings are not necessarily quoted in Sass. Don't ask me why.

$css-tricks-is: #b4d455, 42, awesome;

In any case, I highly recommand you:

  • keep the braces
  • use commas
  • quote your strings

It will save you some time, trust me.

The Striping Mixin

Let's get to the point of the article: our striping mixin! The main idea is to take advantage of the fact Sass lists can be comma-separated, just like color-stops in gradients. To put it simple, a list like $list: red 20%, blue 55% could be used in a linear-gradient() function as is: linear-gradient($list) outputing linear-gradient(red 20%, blue 55%).

Because we're badasses, we want to make it as flexible as possible. So:

  • we can define a collection of color-stops
  • we can define a list of colors if we want all the stripes to have the same size
  • we define a direction as a default so we can ommit it in some cases

Thus we need two things to turn a regular gradient into a striped one: the list of colors / color-stops (e.g. deepskyblue, tomato, lightgreen or deepskyblue 20%, tomato 35%, lightgreen 62%) and an optional direction. Let's start with the skeleton:

@mixin stripes($colors, $direction: "to bottom") { 
    /* Core */
}

As of $colors, there are 3 different scenarios available:

  • The user passes a comma-separated list of color-stops: (deepskyblue 20%, tomato 35%, lightgreen 62%),
  • The user passes a comma or space-separated list of colors: (deepskyblue, tomato, lightgreen),
  • The user passes a single color: deepskyblue or (deepskyblue).

Everything else will either dump out invalid output or throw a Sass error. The mixin is meant for informed developers in a development environment so it's really no big deal if we don't cover every single edge case.

The very first thing we have to find out is whether we are dealing with a list of colors or a list of color-stops. The easiest way to find out is to check the first item in the $color list (with type-of()). If it is a list, then we have to deal with color-stops else the user wants all stripes to have the same width and it's pretty easy for us.

Unfortunately, we cannot do $auto : !(type-of($first-item) == list) since Sass doesn't recognize this as valid syntax. So to check, we can use the if() Sass function which comes close to the var = condition ? true : false statement of other languages.

$auto: if( type-of(nth($colors, 1)) == list, false, true );

To sum up, if $auto is true, it means all stripes will have the same size so the calculations are handled by Sass. If it's false, it means we have to deal with custom stops. We still need two variables before looping through colors: one in case we are running in auto-mode to define the size of a stripe; and one to store our color-stops while looping (later used in a linear-gradient function).

$stripe-width: 100% / length($colors); /* Only used in auto mode */
$gradient: ();

Now we can loop through colors / color-stops and add things to our $gradient variable. To add a numeric component to our loop, we use a @for loop instead of a @each loop. It doesn't make things much harder though. We also declare 2 new variables inside the loop: one for the current item and one to store the current color-stop before appending it to $gradient.

@for $i from 1 through length($colors) {
    $item: nth($colors, $i);
    $dump: ();
}

This is where things get complicated. First, we have to differenciate auto mode from hard mode: color-stops are not the same. In auto mode, they are calculated which means in the first loop run (when $i equals 1) the "previous color-stop" equals 0% ($stripe-width * ($i - 1)). In hard mode, we have to check whether we're in the first loop run or not because nth($colors, 0) isn't allowed; it throws a Sass error. Let's check the code:

@for $i from 1 through length($colors) {
    $item: nth($colors, $i);
    $dump: ();

    /* If we're in auto-mode,
     * $item equals a color,
     * color-stops are automatically calculated based on $i
     */
    @if $auto == true {
        $dump: $item $stripe-width * ($i - 1), $item $stripe-width * $i;
        /*      red   0%                      , red   50%
         * ^ This is what the first loop run would output with a 2 colors gradient
         */
    }
    
    /* If we're in hard-mode
     */
    @else {
        /* We check if it is the first run loop;
         * if it isn't, we add the current color with the previous stop
         */
        @if $i > 1 {
          $previous-item: nth($colors, $i - 1);
          $dump: append($dump, nth($item, 1) nth($previous-item, 2));
        }
        /* No matter what, 
         * we add the new color stop
         */
        $dump: append($dump, $item);   
   }

   /* And no matter what, 
    * we append $dump to $gradient using join(),
    * separating both with a comma by forcing it as a 3rd argument
    */
   $gradient: join($gradient, $dump, comma);
}

At the end of the loop, we have a well formated list ready to be used in a linear-gradient. We can now safely use it as background-image. Even with the Compass built-in mixin to output all the prefixes. Here is the whole mixin now:

@mixin stripes($colors, $direction: "to bottom") {  
    $stripe-width: 100% / length($colors);
    $auto:         if( type-of(nth($colors, 1)) == list, false, true );
    $gradient:     ();
    
    @for $i from 1 through length($colors) {
        $item: nth($colors, $i);
        $dump: ();
      
        @if $auto == true {
            $dump: $item $stripe-width * ($i - 1), $item $stripe-width * $i;
        }
      
        @else {   
            @if $i > 1 {
                $previous-item: nth($colors, $i - 1);
                $dump: append($dump, nth($item, 1) nth($previous-item, 2));
            }
            $dump: append($dump, $item);
        }

        $gradient: join($gradient, $dump, comma);
    }		

    @include background-image(linear-gradient($direction, $gradient));
}

Demo

As a demo, I took the header of Treehouse's blog: a line made of about 50 colored stripes. It looks absolutely lovely. They currently use 50 spans. Ouch! They could use stripped gradients instead, and it's easy now with this mixin.

I made two versions: the first one is running in auto-mode, meaning all stripes have the same width; the second one use custom color-stops to reproduce Treehouse's effect.

/* Colors only (auto-mode) */
$treehouse-auto: #fa9300, #66c9ee, #c9c9c9, #82b964, #d24d33, #fffbdb, #2e77bb, #6bd5b1, #f87aa0, #c9c9c9, #72664e, #ccd600, #fffbdb, #df620e, #993838, #ff9600, #d24d33, #8960a7, #82b964, #f87aa0, #d43f3f, #668000, #ff9600, #8960a7, #c9c9c9, #993838, #ccd600, #668000, #f4cc13, #72664e, #fa9300, #66c9ee, #c9c9c9, #82b964, #ccd600, #fffbdb, #2e77bb, #6bd5b1, #f87aa0, #c9c9c9, #fa9300, #66c9ee, #c9c9c9, #82b964, #ccd600, #fffbdb, #fa9300;

/* Color-stops (hard-mode) */
$treehouse-hard: #fa9300 2.61%, #66c9ee 4.35%, #c9c9c9 6.96%, #82b964 9.13%, #d24d33 11.3%, #fffbdb 13.91%, #2e77bb 16.52%, #6bd5b1 17.82%, #f87aa0 19.12%, #c9c9c9 21.29%, #72664e 23.9%, #ccd600 26.07%, #fffbdb 28.68%, #df620e 31.29%, #993838 33.03%, #ff9600 34.33%, #d24d33 36.94%, #8960a7 39.55%, #82b964 42.16%, #f87aa0 43.36%, #d43f3f 45.63%, #668000 47.8%, #ff9600 50.41%, #8960a7 51.71%, #c9c9c9 53.88%, #993838 55.18%, #ccd600 57.79%, #668000 59.53%, #f4cc13 60.83%, #72664e 63.44%, #fa9300 66.05%, #66c9ee 67.35%, #c9c9c9 69.96%, #82b964 71.7%, #ccd600 74.31%, #fffbdb 76.92%, #2e77bb 79.53%, #6bd5b1 80.4%, #f87aa0 81.7%, #c9c9c9 83.87%, #fa9300 86.04%, #66c9ee 87.78%, #c9c9c9 90.39%, #82b964 92.56%, #ccd600 95.17%, #fffbdb 97.34%, #fa9300 100%;

/* Using a pseudo-element to display it, no extra markup */
.header:after {    
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: .5em;
    // Auto
    @include stripes($treehouse-auto, to right);
    // Hard
    @include stripes($treehouse-hard, to right);
}

As a result you can see the auto-mode at the top of the following pen and the hard-mode at the bottom. The later definitely looks better.

Check out this Pen!

Another use case could be helping out with the fluid width columns of equal height trick (see the Doug Neiner method).

Final words

I think we're done team. If you prefer a function to a mixin, it is fairly easy to edit: simply change @mixin to @function and the background-image line to something like @return linear-gradient(#{$gradient}, #{$linear}) then use it with background-image: stripes($colors). I personally prefer using a mixin, but it's really up to you.

What do you think?

If you feel like you could make the code easier, please be sure to tell! Thanks for reading. :)

icon-closeicon-emailicon-linkicon-menuicon-searchicon-tag