Article Archives

The Extend Concept

All three of the most popular CSS preprocessors support extend. I don't have any data, but in my experience this feature is confusing at first and thus a bit under used. I thought we could talk a bit about how it works, why and when to use it, some gotchas, and what it might be like in the future.

(more…)

Centering Percentage Width/Height Elements

If you know the exact width/height of an element, you can center it smack dab in the middle of its parent element easily with this classic trick: top and left set to 50% and negative margins half the width and height of the element. That's great if you know the width and height of the element you're trying to center, but what if they are percentages?

(more…)

An Intro to Hitch.js and the Extensible Web

The following is a guest post by Brian Kardell. Brian wrote me after I linked up Hitch.js a few weeks ago to give me more insight. It's pretty interesting stuff, so I thought we should share that here. Hitch is an artifact of a larger "Extensible Web" movement, including a manifesto, community group, and funny word.

What is Hitch.js exactly?

Hitch is a proof-of-concept “prollyfill engine” (we'll define that later) specializing in CSS selectors. It gives you jQuery-style selector plugins right in CSS itself. It’s based on proposals from the CSS working group list a few years ago by Yehuda Katz, myself and a few others as well as some very long email threads with Google’s Tab Atkins and Mozilla’s Boris Zbarsky. During the discussions I found myself wanting to prove something, so I’d write a little code. In the end I worked with my friend Clint Hill stringing it together and re-working it into a usable open-source project that might give developers some immediate value. That's Hitch.js.

Has it done that?

I think so. It’s done a few things: First, it shines some light on yet another example of what Alex Russell and Yehuda Katz are talking about in the Technical Architecture Group about a need for layering the design of things and how, for a lot of things, developers wind up re-implementing things that the browser already does much better because we’re sealed off from at high levels and we can’t tweak just one piece. In CSS, we’re missing some primitives and good extension points along the way. It is surprisingly difficult to add this sort of thing. It has also helped to convince certain key members of the CSS Working Group that CSS needs some things like this. Tab wrote about it on his blog in a New Year’s Resolution post. I am pretty confident that we will wind up with some good new abilities in CSS like in the next few years. Until that time, we have Hitch.

What would you really use it for?

This is the key question, whether it was provided via Hitch or natively, what could you do with this new found power? I think you could help change the Web forever. I know that sounds big, but I think it is. We could use it to help better the whole model of how we think about standards. Consider this: CSS 2 became a W3C Recommendation in May 1998. We might still think of “CSS 3″ as being something relatively new – but actually they published the first draft for CSS 3 in August 1999. Way back then, they were discussing way more selector power than is in CSS Selectors Level 3 today. Think about that for a moment. If you were a toddler when they started CSS 3, you would be graduating from high school now. There are a lot of reasons for that, but even if that is artificially long by a factor of 5, it still means that you have to wait a few years for something to make it through the process until anyone really gets to use it. Then it’s sometimes only in nightlies, or behind a flag, so you can’t really use it for anything “real”. Historically then it would be added behind a prefix and a few daring souls might start using it, but it’s hard because it only works in a few browsers. That meant that realistically it was a few more years out until it is usable by a wide enough audience to find out that, actually “I don’t care for half of these selectors and why didn’t they do X instead?” This is exacerbated by the fact that once it is that far, you are really hard pressed to convince anyone to change it because that means potentially “breaking the Web” as they like to say. In a word, that sucks.

How would it help change that? Is this related to the Extensible Web?

What if, instead of that model, I could let you use CSS Selectors Level 4 or 5 – or any proposed selectors right now in a way that was reasonably performant and you could know that the implementation wouldn’t change out from underneath you? It should be possible right? If we use polyfills to “fill the gaps” providing reasonable implementations for standards on the least capable older browsers then why not build reasonable implementations of the proposals in the first place that work on modern browsers – prollyfills - so that we could evaluate, iterate and compete. If we did, we could cut to the chase right? You could complain that they were no good now before they went any further. If we did it out in public on GitHub, you might even be able to fork them and make them better – and you probably would, because, lets face it: Way more people use GitHub than participate in Web Standards discussions. We might even collect data on use, complaints, stability and vendor reviews to determine when one is “baked” enough to worry about moving on to native implementations and prioritize them quickly.

Can you give me some examples?

Let’s say there is something in the Selectors Level 4 proposal that you think might be useful, like the :local-link pseudo-class which lets you select links that are within your domain and at varying URL levels (as you often have in navigation links). Is it? Are you sure you even understand it? With Hitch, we can develop a prollyfill for that and share it – in fact, we did - you can view a demo of it. That means you can actually use it for something real today. You can help make it better too, fork it on GitHub and improve it you can send me a pull request, share your use cases, open issues, or add some reftests. Any feedback that you send, we will relate up to the CSS Working Group.

Here's an even more simple example. We'll make a selector that only selects external links. First link up the Hitch.js:

<script src="http://hitchjs.com/dist/hitch-0.6.3.js"></script>

Then use the Hitch syntax for adding a new selector. We'll make sure the hostname of the href matches the hostname of the window.

Hitch.add([{
  
  type: 'selector',
  name: '-links-external', 
  base: '[href]',
  filter: function (match, argsString, o) {
    if (!match.hostname) {  
      return false;
    }
    return match.hostname !== window.location.hostname;
  }
  
}]);

Then we can use the name we set up there in our CSS. Note the special attribute on the CSS that ensures Hitch parses it.

<style data-hitch-interpret>
  a:-links-external() {
    background-color: yellow;
  }
</style> 
Check out this Pen!

Or, let’s say that you had a proposal for a selector that isn’t in any draft: You could write a prollyfill and submit a draft by creating a git just like the one above and share it with the CSS Working Group. In fact, this has happened already and you can read about it in our post About :time – Taming the standards process. Even better, what if browser vendors followed this same pattern whenever possible? Well, that’s happened too: Adobe did something similar with a regions proposal – they didn’t use Hitch because they didn’t know about it, but they wrote a kind of one-off that does something similar. Mozilla did this with X-Tags and Google with Polymer – both of which can more freely evolve, be used in any modern browser and even maybe compete a little outside the browser before we rush in and commit. We’ve followed the same basic idea with Futures/Promises and with Navigation Controller. I consider these all great successes that helped us coordinate a lot of groups and get a lot of minds together in new ways.

How does Hitch relate to Web Components?

It has some stuff about Web Components, but those were based on an earlier draft. It pre-dates Mozilla’s X-Tags or Google’s Polymer and we have no real interest in competing with them. In fact, we’d love to collaborate. Both are considerably better and based off updated work. It just turned out that internally we were doing 95% of the stuff necessary to make a simple element “upgrade” happen easily, so we exposed it. If you just want to break down into modular ‘widgets,’ you can probably get away without more. But that isn’t what it's about.

You mentioned that Hitch wasn’t a pre-processor, why not?

As it stands today, Hitch includes some aspects of a CSS pre-processor, but it’s not a pre-processor. It isn’t intended to be a replacement for things like Sass, it just turns out that internally exposing a bit of simple pre-processing is easy, so we expose it. If you just need some simple token replacement, you can probably get away without more, but that isn’t what it is about. In fact, the input to the actual “engine” in Hitch isn’t even CSS, but a kind of parse tree. It’s layered so that we can move the pre-processing piece out if we can partner up with existing things like Sass. We kept it simple for now because some people don’t have a rich pre-processor and don’t want one and we honestly don’t want to try to compete with those guys. It’s better for us to work together with them for that piece as an optimization.

How does all of this relate to the Extensible Web?

That’s what The Extensible Web Manifesto is all about – changing the way we think about standards. Hitch predates this, so I can’t honestly say that it is the “perfect” example of it all. Several of us came to very similar conclusions about the same time and we’ve been discussing for a long time now and honing it all. But it does illustrate, at a high level at least, some of how we’d like to change the model and make it possible for good developers to help #extendthewebforward. If any of this sounds compelling to you, I’d encourage you to go give it a read. And hopefully to sign it yourself. Then tell a friend!

The Layered Look: Better Responsive Images Using Multiple Backgrounds

The following is a guest post by Parker Bennett. Parker has written for CSS-Tricks before, in his article Crop Top dealing with the positioning of fluid images. This is a great follow up to that, presenting another option in the never-ending responsive images saga. It's also an interesting contrast to yesterday's post on responsive images - so you can see how very different the approaches to this problem can be.

(more…)

Making Sass talk to JavaScript with JSON

The following is a guest post by Les James. Like many of us, Les has been gunning for a solution to responsive images that works for him. In this article he shares a technique he found where he can pass "named" media queries from CSS over to the JavaScript, which uses those names to swap out the image for the appropriate one for that media query. And even automate the process with Sass. HTML purists may balk at the lack of true src on the image, but at this point we gotta do what we gotta do.

Current proposed responsive image solutions require that you inline media query values into HTML tags.

<picture>
    <source media="(min-width: 45em)" src="large.jpg">
    <source media="(min-width: 18em)" src="med.jpg">
    <source src="small.jpg">
    <img src="small.jpg" alt="">
</picture>

This is a problem for me. I like my media queries in one spot, CSS. The above example doesn't feel maintainable to me, and part of that might be due to my approach to RWD. I use the Frameless grid approach to creating layouts. I tell Sass how many columns I want in a layout and it generates a media query to fit it. What this means is that I only think in column counts and I actually have no idea what the actual values of my media queries are.

When adapting this approach to responsive images, I needed a way to provide meta data around my breakpoints. So when I create a breakpoint, I give it a label. I've recently been a fan of labels like small, medium and large but the labels could be anything you want. The point is that you name your breakpoints with something meaningful. The goal is to pair those names to matching sources defined in my HTML. The first step is to format our label into something JavaScript can parse.

Sass to JSON

When I create a breakpoint I call upon a Sass mixin I created. The column count creates a min-width media query to fit that column count. The label gives a name to our media query.

@include breakpoint(8, $label: "medium") {
    /* medium size layout styles go here */
}

The breakpoint mixin passes that label to a function which formats it into a string of JSON.

@function breakpoint-label($label) {
    @return '{ "current" : "#{$label}" }';
}

JSON to CSS

Now that we have our label converted to JSON, how do we get it into our CSS? The natural fit for a string is CSS generated content. I use body::before to hold my string because it's the least likely spot for me to actually use for display on the front end. Here is how the label finds its way into CSS from my breakpoint mixin.

@if($label) { body::before { content: breakpoint-label($label); } }

Unfortunatly I have to support older browsers and they will have trouble reading our CSS generated content with JavaScript. So we have to place our JSON in one more spot to gain further compatibility. For this I'm going to add our JSON as a font family to the head.

@if($label) {
    body::before { content: breakpoint-label($label); }
    .lt-ie9 head { font-family: breakpoint-label($label); }
}

CSS to JS

Our layout label is now sitting in a JSON string in our CSS. To read it with JavaScript we turn to our friend getComputedStyle. Let's create a function that will grab our JSON and then parse it.

function getBreakpoint() {
    var style = null;
    if ( window.getComputedStyle && window.getComputedStyle(document.body, '::before') ) {
        style = window.getComputedStyle(document.body, '::before');
        style = style.content;
    }
    return JSON.parse(style);
}

For browsers that don't support getComputedStyle we need to throw in a little polyfill and grab the head font family instead.

function getBreakpoint() {
    var style = null;
    if ( window.getComputedStyle && window.getComputedStyle(document.body, '::before') ) {
        style = window.getComputedStyle(document.body, '::before');
        style = style.content;
    } else {
        window.getComputedStyle = function(el) {
            this.el = el;
            this.getPropertyValue = function(prop) {
                var re = /(\-([a-z]){1})/g;
                if (re.test(prop)) {
                    prop = prop.replace(re, function () {
                        return arguments[2].toUpperCase();
                    });
                }
                return el.currentStyle[prop] ? el.currentStyle[prop] : null;
            };
            return this;
        };
        style = window.getComputedStyle(document.getElementsByTagName('head')[0]);
        style = style.getPropertyValue('font-family');
    }
    return JSON.parse(style);
}

There is a major problem with our function right now. Our JSON is passed as a string which means that it is wrapped in quotes, but what kind of quote depends on which browser you are using. WebKit passes the string wrapped in single quotes. Firefox passes the string wrapped in double quotes which means that it escapes the double quotes inside of our JSON. IE8 does something really wierd and adds a ; } to the end of our string. To account for these inconsistancies we need one more function to normalize our JSON before we parse it.

function removeQuotes(string) {
    if (typeof string === 'string' || string instanceof String) {
        string = string.replace(/^['"]+|\s+|\\|(;\s?})+|['"]$/g, '');
    }
    return string;
}

Now before parse the JSON in the return of our getBreakpoint function we just pass the string through our removeQuotes function.

return JSON.parse( removeQuotes(style) );

Image Source Matching

JavaScript can now read the label that we defined for each breakpoint. It's trivial at this point to match that label to a responsive image source. Take the following image for example.

<img data-small="small.jpg" data-large="large.jpg">

When the active media query is small, we can have JavaScript match that to data-small and set the source of our image to small.jpg. This works great if you've declaired a source for every breakpoint but as you can see in our example we don't have a source defined for medium. This is a very common scenario. The small image can typically work in larger layouts. Maybe the medium layout just added a sidebar and our image size didn't change. So how does JavaScript know to pull the small source when the layout is medium? For this we need ordering.

Sass List to JavaScript Array

Every time we create a breakpoint we can store that label in a Sass list. In our breakpoint mixin we can append the label to our list.

$label-list: append($label-list, $label, comma);

Assuming that our list defaults to a pre-populated mobile label of small the following breakpoints will create a list of small, medium, large.

@include breakpoint(8, $label: "medium");
@include breakpoint(12, $label: "large");

The order you declare your breakpoints in Sass will determine the order of your labels. Let's add this Sass list as an array to our JSON function.

@function breakpoint-label($label) {
    $label-list: append($label-list, $label, comma);
    @return '{ "current" : "#{$label}", "all": [#{$label-list}] }';
}

Now in addition to JavaScript knowing the current breakpoint label it can look at the array we passed and know their order. So if the layout is medium and no matching data attribute is found on our image, JavaScript can find medium in our label array and walk backwards through that array until a matching source is found.

In Summary

This responsive image solution does something really important for me. By tagging media query values with labels I create flexibility and simplicity. If I change the size of a breakpoint I only have to change it in one place, my Sass. My HTML image sources aren't dependent on the value of my media queries, just their name.

Although I've accomplished this with Sass, it's actually not necessary. You can manually write your JSON string into your media queries, Sass just helps automate the process. Here is a simple Pen that uses pure CSS.

Check out this Pen!

To see a more robust, production quality implementation of this technique check out the code behind my framework Breakpoint.

Please note, if you want your image tags to be valid then stub them with a source like src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" and please, make sure you provide a <noscript> fallback.

My hope for sharing this is that it spurs further discussion and ideas around abstracting the complexities and maintainability of responsive images. I'm curious to hear your thoughts and if you have ways to improve this.

We all stand on the shoulders of giants. Much credit and inspiration for this is due to Jeremy Keith's post Conditional CSS and Viljami Salminen's detectMQ.

More on Sass & JSON Working Together

  • Hugo Giraudel has a library for encoding and decoding JSON from Sass.
  • Robert Balicki has a library for turning JSON into Sass variables.

CSS-Tricks Chronicle XIV

I've had the opportunity to be a guest on a couple of podcasts lately. I'm on episode 18 of The Gently Mad podcast with Adam Clark.

I'm also on Authored Content episode 22 (video) with Morten Rand-Hendriksen, James Williamson, and Ray Villalobos.

On both I get the chance to talk about some projects I've worked on both past and present as well as hot topics of the day!


Speaking of podcasts, ShopTalk is going great. We've had some fun episodes lately like with Raquel Velez and Val Head. Also a RAPIDFIRE episode, which there will be more of in the coming months since we air those when Dave or I has to be gone a particular week.


Speaking of ShopTalk, Dave and I did a live ShopTalk show at Front End Design Conference. We typically record "live", but this was our first time in front of a live audience. It was super fun and hopefully we get to do it again sometime. We're hoping there is a good audio recording of it so we can post it as a real show, so it'll come across iTunes n' stuff.

It was the fifth year of the Front End Design Conference and it was just fantastic as always. If you're looking for one to attend, make sure to mark this one down as soon as they announce it next year.

I was stoked to see CodePen used by a number of presenters to show off demos during the conference.


Speaking of CodePen, that's going really well also. We've had some pretty big features roll out lately like using other Pens as resources, including including HTML, and showing errors right in the editor.

We have tons more features and refinements large and small underway so keep coming back for more. We work on it all day every day. In fact the whole CodePen team is at my house for a few weeks for a super code jam.


There has been some good threads in the forums lately like Opinions on CSS Frameworks, Computer for Web Programming, a thread about Macaw, and How big should my background image be?. I like seeing that the opinion threads are alive and well, as well as specific technical stuff getting solved left and right.


You may have noticed a decent amount of guest posts happening here on CSS-Tricks lately. It wasn't planned really, they just kind of happen naturally through conversations I have with people who email in about ideas. If you have an interest in writing a guest post to be published here 1) have an idea that you think is really cool and you really care about 2) do some research / make demos 3) contact me and I'll check it out 4) use this template for creating the article.

I don't have a huge budget but if your article is awesome, takes time, and doesn't benefit you otherwise - I'm sure we can work something out.

Replicating Some Of Google Hangouts Chat Design

I've been using Google Hangouts a bunch. It's really pretty great. One on one or group text chat, audio, or video. Text is archived, maintains history, and is searchable. Video / audio is recordable. It works great on desktop and mobile devices and keeps them in sync. It's free. Hard to beat that.

Anyway, on a whim I decided to replicate some of the look of the chat window on desktop. Turns out there is a bunch of interesting stuff that comes up! Radial gradients, pseudo elements and animations, flexbox, and more.

(more…)

Speaker Notes

Rebecca Murphey with tips on speaking. While posted on “Ladies in Tech,” the advice is good for anyone.

I’ve learned that my ability to give the “elevator pitch” for a talk is a great measure of my preparedness.

Intro to Web Workers

Brian Cooksey goes from "I don't really know what Web Workers are" to "OK I totally get Web Workers." on one short article.

...they are scripts that run in their own background thread. Independence from the regular JavaScript event loop means that a worker can churn away at something for a long time and your UI will remain responsive.

A Couple of Best Practices for Tablet-Friendly Design

The following is a guest post by Ben Terrill. Ben is co-author of the e-book Tablet Web Design Best Practices and is the VP of Customer Success at Mobify, where he works on big client sites like British Telecom, Starbucks and Expedia.

The tablet revolution is upon us. New data from Adobe shows that global websites now get more traffic from tablets than smartphones. And yet, a standard desktop site doesn’t work very well on a tablet. The typical desktop 12-pixel font is too small, as are buttons. Images aren’t sharp and, worst of all, some features simply don’t work.

The good news is you don’t have to completely revamp your website. A working desktop site is a great place to start building an effective tablet site. In this article, I’ll share six techniques from Mobify’s latest ebook Tablet Web Design Best Practices for significantly improving desktop websites on tablets.

Go 100% Touch Friendly

One of the best ways to make your desktop website sing on a tablet is to make it touch friendly. If website elements look as though they can be swiped, tapped or pinched, then you’ll need to build in that functionality to make your website tablet ready.

Consider adding elements like carousels and accordions, drawers and panels. Mobify has a variety of open source JavaScript modules you can use for this purpose.

Editor's note: We recently covered the JavaScript for touch-friendly sliders. I also think Royal Slider is a nice slider that is touch-friendly and also responsive.

Bump Up Default Font Size and Line Height

Don’t make users double tap or pinch your content. Instead, increase the font size to at least 16px. You can also use a line height of 1.5 to allow for breathing room between text on content-rich pages, as Mashable does in the example below. Remember, text must always be legible, no matter how a user holds their tablet.

Be Finger Friendly

Our fingers are much clumsier than a cursor, so bumping up the spacing between different touch targets will improve user accuracy. And, make those touch targets big! Our fingertips typically require upwards of 44px to comfortably fit within a touch target so design for that.

Make each touch target at least 44px by 44px and use padding rather than margin. Padding increases the actual tappable area, whereas margin simply increases the whitespace around the element.

Enable Contextual Keyboards

The great thing about software keyboards is that they’re dynamic. That is, you can change their layout to suit context. For instance, if your input field requires an email address, the keyboard should feature the ‘@’ symbol, underscores and hyphens. If the user is asked to input a phone number, provide a numeric keypad. Try using the following input types on form fields:

  • Standard keyboard | <input type="text" />
  • URL parameters | <input type="url" />
  • Email-specific keyboard | <input type="email" />
  • Numeric keyboard | <input type="text" pattern="[0-9]*" />

Example of a better numeric keyboard (iOS on left, Android on right) (via)

Editor's note: I also detailed data about HTML5 input attributes/types/elements. It's getting a smidge old, but still useful.

Font-Based Icons for the Win

Resolutions and pixel densities on tablet screens are far greater than on desktop and laptop screens. As a result, graphics can look pixelated if they’re not designed with high resolution screens in mind. For this reason, font-based icons are a good choice because they scale well on super high­ resolution displays; they’re easy to colour and shade using CSS; and they only require one HTTP request to download. Plus, you don’t have to deal with a sprite sheet.

Create your own icon font sets, or use existing sets like Font Awesome, glyphish, iconsweets, symbolset, or icnfnt.

Editor's note: I once did a massive roundup of icon fonts (which I still have to add to). I'm a fan of using these HTML techniques for adding them to the page, which keep them accessible. I'm also a fan of IcoMoon for the creating trimmed down, customized icon font sets.

Performance is Design

Modern web design techniques, like responsive design, can cripple website performance. Since 57% of users are likely to leave your website if it takes 3 seconds to load, performance considerations are critical. Some tips for improving mobile website performance include compressing images and concatenating CSS and JavaScript to reduce the number of HTTP requests and overall page size. With these fixes, you’ll notice significantly speedier page load time and happier, higher converting users. Use tools like Uglify, Sass, Compass and Mobify.js to automate performance improvements.

Editor's note: I cover some of these performance techniques and some others in #114: Let’s Do Simple Stuff to Make Our Websites Faster

Go Forth!

With these tablet transformation techniques in your toolbox, there’s no reason to get stressed out about not having a totally tablet-optimized website. For more ways to make your desktop site tablet friendly, read Mobify’s free ebook, Tablet Web Design Best Practices.

Poll Results: Mobile Web Design Responsibility

In early 2008, I asked the question:

What is your opinion as to the web designers role in mobile design?

The two choices were:

  • It is my job to make sure the website looks and functions well on mobile devices.
  • It is the mobile device's job to make sure my website looks and functions well.

Back then, 55% thought it was the mobile devices job. The vibe was more "I'm just gonna keep building websites how I have been and these new devices can handle making them work."

In April 2013, I started the exact same poll again. Perhaps unsurprisingly, the 55% majority position has shrunk to just 21% of people. The other 79% consider it there job to build websites that look and function well on mobile devices.

I forced people to choose one or the other to get a sense for where the majority of the responsibility lies, but I'm sure most of us agree that there is shared responsibility. Mobile devices need to support standards and should do all they can do to make the web experience great. But the polls are showing (and I agree) that ultimately the responsibility lies on the people making websites to make them work wherever they are used.

The JavaScript Behind Touch-Friendly Sliders

The following is a guest post by Kevin Foley. Kevin is a developer at Squarespace doing cool stuff with their developer platform, among other things. He was recently working on a swipeable image gallery and he agreed to share some of that work here!

A few weeks ago Chris posted a tutorial for creating a Slider with Sliding Background Images. Around the same time I was working on some new swipeable galleries, so Chris suggested I write up a tutorial for how to add swipe support to his slider. Here it is!

When creating a swipeable gallery there are two techniques — that I know of — you can choose from. You can animate the scroll position, or move the element using translate. There are pros and cons to each.

Using Translate

Moving the slider with translate gives you the advantage of hardware acceleration and subpixel animation. However, on the initial touch event you might notice a small delay — only a few tens of milliseconds — before the slider starts moving. This isn’t very well documented, I’ve just noticed it in my experience.

Using Overflow Scroll

Overflow scroll is extremely responsive to the initial touch because it’s native to the browser. You don’t have to wait for the event listener in JavaScript. But you lose out on all the smoothness of moving elements with translate.

For this tutorial we’re going to use translate because I think it looks better.

The HTML

The HTML in this example is going to differ from Chris’s original example. Instead of setting the image as a background image, we’re going to set it as an element. That will allow us to move the image to gain that cool panning effect using translate instead of animating the background position.

<div class="slider-wrap">
  <div class="slider" id="slider">
    <div class="holder">
      <div class="slide-wrapper">
        <div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7347/8731666710_34d07e709e_z.jpg" /></div>
        74
      </div>
      <div class="slide-wrapper">
        <div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7384/8730654121_05bca33388_z.jpg" /></div>
        64
      </div>
      <div class="slide-wrapper">
        <div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7382/8732044638_9337082fc6_z.jpg" /></div>
        82
      </div>
    </div>
  </div>
</div>

The CSS

For the most part the CSS is the same as Chris’ so I won’t rehash how to set up the layout. But there are a few key differences.

Instead of simply adding overflow scroll, we need to animate the slides. So for that we’re going to use a class to set up the transition and add it with JavaScript when we need it.

.animate { transition: transform 0.3s ease-out; }

IE 10 handles touch events differently than mobile Webkit browsers, like Chrome and Safari. We’ll address the Webkit touch events in JavaScript, but in IE10 we can create this entire slider (almost) with nothing but CSS.

.ms-touch.slider {
  overflow-x: scroll;
  overflow-y: hidden;
  
  -ms-overflow-style: none;
  /* Hides the scrollbar. */
  
  -ms-scroll-chaining: none;
  /* Prevents Metro from swiping to the next tab or app. */
  
  -ms-scroll-snap-type: mandatory;
  /* Forces a snap scroll behavior on your images. */
  
  -ms-scroll-snap-points-x: snapInterval(0%, 100%);
  /* Defines the y and x intervals to snap to when scrolling. */
}

Since these properties are probably new to most people (they were to me, too) I’ll walk through each one and what it does.

-ms-scroll-chaining

The Surface tablet switches browser tabs when you swipe across the page, rendering all swipe events useless for developers. Luckily it’s really easy to override that behavior by setting scroll chaining to none on any given element.

-ms-scroll-snap-type

When set to mandatory, this property overrides the browser’s default scrolling behavior and forces a scrollable element to snap to a certain interval.

-ms-scroll-snap-points-x

This property sets the intervals the scrollable element will snap to. It accepts two numbers: the first number is the starting point; the second is the snap interval. In this example, each slide is the full width of the parent element, which means the interval should be 100% — i.e. the element will snap to 100%, 200%, 300%, and so on.

-ms-overflow-style

This property lets you hide the scrollbar when you set it to none.

The JavaScript

The first thing we have to do in JavaScript is detect what kind of touch device we’re using. IE 10 uses pointer events while Webkit has “touchstart,” “touchmove,” and “touchend.” Since the IE 10 slider is (almost) all in CSS we need to detect that and add a class to the wrapper.

if (navigator.msMaxTouchPoints) {
  $('#slider').addClass('ms-touch');
}

Pretty simple. If you tested the slider at this point it would be a functioning swipeable slideshow. But we still need to add the panning effect on the images.

if (navigator.msMaxTouchPoints) {
  $('#slider').addClass('ms-touch');

  // Listed for the scroll event and move the image with translate.
  $('#slider').on('scroll', function() {
    $('.slide-image').css('transform','translate3d(-' + (100-$(this).scrollLeft()/6) + 'px,0,0)');
  });
}

And that’s it for IE 10.

Now for the webkit way. This will all be wrapped in the else statement. First we’ve just got to define a few variables.

else {
  var slider = {

    // The elements.
    el: {
      slider: $("#slider"),
      holder: $(".holder"),
      imgSlide: $(".slide-image")
    },

    // The stuff that makes the slider work.
    slideWidth: $('#slider').width(), // Calculate the slider width.

    // Define these as global variables so we can use them across the entire script.
    touchstartx: undefined,
    touchmovex: undefined, 
    movex: undefined,
    index: 0,
    longTouch: undefined,
    // etc

Then we need to initialize the function and define the events.

    // continued

    init: function() {
      this.bindUIEvents();
    },

    bindUIEvents: function() {

      this.el.holder.on("touchstart", function(event) {
        slider.start(event);
      });

      this.el.holder.on("touchmove", function(event) {
        slider.move(event);
      });

      this.el.holder.on("touchend", function(event) {
        slider.end(event);
      });

    },

Now for the fun stuff that actually makes stuff happen when you swipe the slider.

Touchstart

On the iPhone (and most other touch sliders) if you move the slider slowly, just a little bit, it will snap back into its original position. But if you do it quickly it will increment to the next slide. That fast movement is called a flick. And there isn’t any native way to test for a flick so we’ve got to use a little hack. On touchstart we intitialize a setTimeout function and set a variable after a certain amount of time.

this.longTouch = false;
setTimeout(function() {
  // Since the root of setTimout is window we can’t reference this. That’s why this variable says window.slider in front of it.
  window.slider.longTouch = true;
}, 250);

We’ve also got to get the original position of the touch to make out animation work. If you’ve never done this before, it’s a little strange. JavaScript lets you define multitouch events, so you can pass the touches event a number that represents the amount of fingers you’re listening for. For this example I’m really only interested in one finger/thumb so in the code sample below that’s what the [0] is for.

// Get the original touch position.
this.touchstartx =  event.originalEvent.touches[0].pageX;

Before we start moving the slider I’m going to remove the animate class. I know there is no animate class on the elements right now, but we need this for the subsequent slides. We’ll add it back to an element on touchend.

$('.animate').removeClass('animate');

Touchmove

The touchmove event behaves similarly to scroll events in JavaScript. That is, if you do something on scroll it’s going to execute a bunch of times while the scroll is occuring. So we’re going to get the touchmove position continuously while the finger/thumb is moving.

// Continuously return touch position.
this.touchmovex =  event.originalEvent.touches[0].pageX;

Then we’ll do a quick calculation using the touchstart position we got in the last event and the touchmove position to figure out how to translate the slide.

// Calculate distance to translate holder.
this.movex = this.index*this.slideWidth + (this.touchstartx - this.touchmovex);

Then we need to pan the image, like Chris did in the original example. We’re going to use the same magic numbers he did.

// Defines the speed the images should move at.
var panx = 100-this.movex/6;

Now we need to add in some logic to handle edge cases. If you’re on the first slide or the last slide this logic will stop the image panning if you’re scrolling in the wrong direction (i.e. toward no content). This might not be the best way to handle this, but it works for me right now.

if (this.movex < 600) { // Makes the holder stop moving when there is no more content.
  this.el.holder.css('transform','translate3d(-' + this.movex + 'px,0,0)');
}
if (panx < 100) { // Corrects an edge-case problem where the background image moves without the container moving.
  this.el.imgSlide.css('transform','translate3d(-' + panx + 'px,0,0)');
 }

Touchend

In the touchend event we’ve got to figure out how far the user moved the slide, at what speed, and whether or not that action should increment to the next slide.

First we need to see exactly how far the distance of the swipe was. We’re going to calculate the absolute value of the distance moved to see if the user swiped.

// Calculate the distance swiped.
var absMove = Math.abs(this.index*this.slideWidth - this.movex);

Now we’re going to figure out if the slider should increment. All the other calculations in this example are based on the index variable, so this is the real logic behind the script. It checks if the user swiped the minimum distance to increment the slider, or if the movement was a flick. And if it meets either of those two criteria, which direction did the swipe go in.

// Calculate the index. All other calculations are based on the index.
if (absMove > this.slideWidth/2 || this.longTouch === false) {
  if (this.movex > this.index*this.slideWidth && this.index < 2) {
    this.index++;
  } else if (this.movex < this.index*this.slideWidth && this.index > 0) {
    this.index--;
  }
}

Now we add the animate class and set the new translate position.

// Move and animate the elements.
this.el.holder.addClass('animate').css('transform', 'translate3d(-' + this.index*this.slideWidth + 'px,0,0)');
this.el.imgSlide.addClass('animate').css('transform', 'translate3d(-' + 100-this.index*50 + 'px,0,0)');

The Conclusion

So, yea, hooray for IE 10.

But seriously, creating swipeable galleries is kind of a pain, considering it’s such a common idiom on mobile OS’s. And the end result won’t be as good as native swiping. But it will be close.

Here's the complete demo:

Check out this Pen!

But you're best bet is checking it out on your touch device here.

IE 10 Specific Styles

Conditional comments are gone in IE 10. That's good. IE 10 is a very good browser. Feature detection is a better way to go in nearly all cases. But what if you find some styling situation where you absolutely need to target IE 10? I guess you'll have to do this.

(more…)

Hitch

It's kinda like a preprocessor (variables, prefixing...) but it can do much more because it's JavaScript that executes on your page. For instance, it can give you a has selector which can test if an element contains another element or selectors that select based on simple math logic (e.g. :-math-greatest(data-price)).

Crop Top

The following is a guest post by Parker Bennett where he explores some different ways to approach the behavior of fluid and responsive images.

Sometimes you want an image to resize responsively but restrict its height — cropping it then as it widens. Here, we explore three options with various trade-offs.

The happy couple, front and center: background-position: center bottom.

Option One: background-image

Edit on CodePen

Here, in place of an <img>, we create a div with a background-image and use CSS3's dandy new background-size: cover to have it size proportionally. As a bonus, we can easily crop from the top, center, or bottom using background-position.

One potential issue is we need to specify a height for the div to show up. This gives it a fixed height that doesn't scale proportionally (at least not without CSS media queries). When it gets narrow enough, the sides start cropping (this might be preferable, it depends).

Also, a quick check with caniuse.com shows this will fail conspicuously in IE8 (showing the image full size), but thanks to Louis-Rémi Babé, there's a background-size polyfill workaround (though it does require a relative or fixed position, and a z-index). IE8 also needs a polyfill for CSS media queries. There are a couple options.

.bg-image {
  /* image specified in separate class below */
  height: 240px;
  width: 100%; 
}

.bg-image-wedding {
  background-image: url(img/photo-wedding_1200x800.jpg);

  /* lt ie8 */
  -ms-background-position-x: center;
  -ms-background-position-y: bottom;
  background-position: center bottom;

  /* scale bg image proportionately */
  background-size: cover;
    
  /* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
  -ms-behavior: url(https://cdn.css-tricks.com/backgroundsize.min.htc);
  /* prevent scaling past src width (or not) */
  /* max-width: 1200px; */
}

/* example media queries */
@media only screen and (min-width : 768px) {
  .bg-image { height: 320px; }
}

@media only screen and (min-width : 1200px) {
  .bg-image { height: 400px; }
}
That's me in the middle: background-position: center center.

Something to note, background-size: cover will readily upscale larger than the src image's native size (or not, if you set a max-width).*

Still, there are some downsides to using a background-image. It's not as semantic or modular as an img, so it's less straightforward to maintain. You're seemingly stuck with a fixed height or cumbersome CSS media queries. Also, users can't save the image as easily (sometimes preferable).

Option Two: img with a Twist

Edit on CodePen

Here, we use an img with max-width set to a percentage of the containing element so it scales responsively, then wrap it in a div with overflow: hidden and a specified height or max-height.

wedding

When you resize past 700px, the bride disappears.
.crop-height {
  /* max-width: 1200px; /* img src width (if known) */
  max-height: 320px;
  overflow: hidden; 
}

img.scale {
  /* corrects inline gap in enclosing div */
  display: block;
  max-width: 100%;
  /* just in case, to force correct aspect ratio */
  height: auto !important;
  width: auto\9; /* ie8+9 */
  /* lt ie8 */
  -ms-interpolation-mode: bicubic; 
}

As you can see, the bottom of the image now gets cropped as it widens. But what if you want it to crop from the top? Surprisingly, you can — using CSS3's transform:rotate() we add a "flip" class to both img.scale and div.crop-height — flipping the img all the way around.

wedding

There's the happy couple! (Unless you're using IE8 or lower.)
/* apply to both img.scale and div.crop-height */
.flip {
  -webkit-transform: rotate(180deg);
  -moz-transform:    rotate(180deg);
  -ms-transform:     rotate(180deg);
  -o-transform:      rotate(180deg);
  transform:         rotate(180deg);
  /* needed? not sure */
  zoom: 1;
}

img.flip {
  /* if native or declared width of img.scale
     is less than div.crop-height, this will
     flipped img left */
  float: right;
  /* add clearfix if needed */ 
}

Novel, but limited to top-cropping only. And, as you might expect, this doesn't work in IE8, either — perhaps failing less conspicuously (it will just crop from the bottom as before). The bad news is, I haven't found any polyfill options that work because they need a specified height and width.

Option Three: Hybrid Approach

Edit on CodePen

What if we could have the advantages of specifying an img (e.g., using max-height so we get proportional vertical scaling below a certain height), but also the flexible cropping and IE8 polyfill support afforded a background-image? We can!

The img has visibility: hidden, the background-image has background-position: center center.

The trick is to make the responsively-sizing img invisible. With visibility: hidden it retains layout, so we see the background-image behind it. (Since it's the same image source it shouldn't have to download twice.) If you want user-friendly access, you could instead use opacity: 0. Now users can drag the image or right-click to save. (Opacity and background-size need some extra IE8 workaround bits.)

wedding

opacity: 0. A background-image you can drag or right-click to save. Works in IE8 (with help).

Another thought is to use a more compressed proxy img, and use CSS media queries to serve a higher-resolution background-image as needed. This img could even be a proportionately smaller size (e.g., matching your max-height), or watermarked. Check out this CSS-Tricks post on media queries, and this helpful resolution mixin for Sass.

wedding

Here, a 70 KB half-scale img is holding the space for the higher-res background-image.
.crop-height {
    /* max-width: 1200px; /* img src width (if known) */
    max-height: 320px;
    overflow: hidden; }

.bg-image-wedding {
    /* for small devices */
    background-image: url(img/photo-wedding_1200x800.jpg);
    /* lt ie8 */
    -ms-background-position-x: center;
    -ms-background-position-y: bottom;
    background-position: center bottom;
    /* scale bg image proportionately */
    background-size: cover;
    /* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
    -ms-behavior: url(https://cdn.css-tricks.com/backgroundsize.min.htc);
    */ prevent scaling past src width (or not) */
    /* max-width: 1200px; */ }

.invisible {
    visibility: hidden; }

.transparent {
    /* trigger hasLayout for IE filters below */
    zoom: 1;
    /* 0 opacity in filters still displays layout */
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    filter: alpha(opacity=10);
    opacity: 0; }

/* example media query for smaller non-retina devices */
@media
    only screen and (max-device-width : 600px) and (-webkit-max-device-pixel-ratio: 1),
    only screen and (max-device-width : 600px) and (        max-device-pixel-ratio: 1) {
      
     .bg-image-wedding {
       background-image: url(img/photo-wedding_600x400.jpg); 
     }
}

/* example media query for retina ipad and up */
@media
    only screen and (min-device-width : 768px) and (-webkit-min-device-pixel-ratio: 1.5),
    only screen and (min-device-width : 768px) and (        min-device-pixel-ratio: 1.5) {

      .bg-image-wedding {
        background-image: url(img/photo-wedding_1200x800@1.5x.jpg); 
      }
}

Wrapping Up

Until the day where CSS3's object-fit is supported, which may be a while, this hybrid option seems like the best approach to me. Still, it's nice to have options. I hope you got something out of my way-too-thorough exploration. You can take a look at the source code for more, edit on CodePen, or download the example files here. If you have any questions, comments, or corrections, drop me a line: parker@parkerbennett.com.


* You can make an img upscale like a background-image if you want. You just need to "pre-enlarge" it, adding a proportionately larger width and height to the img element itself: <img width="2400px" height="1600px" src="img/photo-wedding_1200x800.jpg /> (edit on CodePen).

Request Quest

Jake Archibald put together an interesting and informative quiz about when browsers actually make requests. I learned a bunch. Some of it might seem like quirky academic knowledge but we all know how often unpredictably weird situations come up in day to day dev work.

Jake wished me to point out that it is unfinished (only works on desktop Chrome) and might hurt your feelings if you can't take browser insult jokes.

The “When Can I Use” Web Widget

A script from Andi Smith that injects a chart of browser support with live data from Can I Use... I really like the idea of using it on any web tech blog post - so the information about feature support stays up to date over time. I think I'll be incorporating it into this site when I get a chance.

Alexis Deveria is cool with it.

It hits a JSON file at raw.github.com through YQL for the data. I wonder if there is a good way to cache it locally (localStorage?) so GitHub doesn't get used like a CDN so much. Or if YQL kinda already does that? Or if we could get it on some true CDN that is happy to get hammered with requests for it. CDNJS?

Using requestAnimationFrame

There used to be just one way to do a timed loop in JavaScript: setInterval(). If you needed to repeat something pretty fast (but not as-fast-as-absolutely-possible like a for loop), you'd use that. For the purposes of animation, the goal is sixty "frames" per second to appear smooth, so you'd run a loop like this: (more…)

A Couple of Use Cases for Calc()

calc() is a native CSS way to do simple math right in CSS as a replacement for any length value (or pretty much any number value). It has four simple math operators: add (+), subtract (-), multiply (*), and divide (/). Being able to do math in code is nice and a welcome addition to a language that is fairly number heavy.

But is it useful? I've strained my brain in the past trying to think of obviously useful cases. There definitely are some though.

(more…)

Sass Style Guide

With more people than ever writing in Sass, it bears some consideration how we format it. CSS style guides are common, so perhaps we can extend those to cover choices unique to Sass.

Here are some ideas that I've been gravitating toward. Perhaps they are useful to you or help you formulate ideas of your own. If you're looking for more examples, Sass Guidelines is another good place to look.

(more…)

3D Button Parallax

The following is a guest post by Alexander Futekov. We recently published an article by Joshua Bader in which a 3D inset look was adjusted as the page scrolled to give it a more realistic interaction. This is similar only Alexander is using an extruded look on buttons and employing a totally different technique.

(more…)

This Website Brought To You By…

I always wanted to write something on all the technologies that a website relies on in order to have been created and work. My attempts have so far failed because it spirals out of control so quickly. Kevin Kelly sums it up:

A web page relies on perhaps a hundred thousand other inventions, all needed for its birth and continued existence. There is no web page anywhere without the inventions of HTML code, without computer programming, without LEDs or cathode ray tubes, without solid state computer chips, without telephone lines, without long-distance signal repeaters, without electrical generators, without high-speed turbines, without stainless steel, iron smelters, and control of fire. None of these concrete inventions would exist without the elemental inventions of writing, of an alphabet, of hypertext links, of indexes, catalogs, archives, libraries and the scientific method itself. To recapitulate a web page you have to re-create all these other functions. You might as well remake modern society.

The article isn't about the web hardly at all, it's about the interconnectivity of tools and how far we'll be set back if that is disrupted. I enjoyed the term "upcreation tool." So many of the tools we use as web workers are tools in which to make more complex tools.

CSS-Tricks Chronicle XIII

I'll be speaking at the upcoming Front End Design Conference in Florida. If you have tickets, see you there! If not, sorry, this one is sold out.

I recently spoke at TXJS, and they recorded the talks, so mine and a bunch of others are available on their Vimeo channel.


Next week I head out for Graves Mountain, as I do every year. So this week I'm planning for that, both getting ready for it as well as getting ready to be unplugged for the week.


ShopTalk is going strong! We have lots of great guests lined up. We've recorded a show in advance to air while I'm away at Graves. I'm sure we'll have a show every week for a very long time to come.

Recent shows include Ben Frain, Pam Selle, and Ben Schwarz.


CodePen is going strong as well. The team has made the huge leap of taking it full time. It's been a touch slow, but it's because both Tim and I moved across the country (me to Milwaukee, WI) and we've been settling in a bit. We're also working on big new features. There will be little new stuff coming here and there, but a lot of time has been sunk into big stuff that'll take a bit to get out.

The Patten Rodeo is back as well, in Season Two.

There are also CodePen PENS now, as well as stickers, and get get both if you order a T-Shirt.


Kern and Burn have a book called Conversations With Design Entrepreneurs and there is a bit of an interview with me in there. I got the book and it is super nice. One of the nicest feeling and reading books I have.


I have a few new articles on The Pastry Box Project. One is a story of a person opening a mustard packet and... well just take of that one what you will. The other is the only bit of life advice I have to offer.


I have some ideas burning for new stuff for The Lodge so I'll be launching into that the next few months. Nothing to share yet, but I'll let you know. I also have a nice list cooking for CSS-Tricks v11. It probably won't be a huge redesign, but more re-align-y focusing on enhanced functionality.

Replace the Image in an <img> with CSS

The following is a guest post by Marcel Shields. Marcel in a difficult place where he needed to change the image on a page but didn't have access to the HTML. Rare, but I'm sure we've all be in weird situations like this. He explains how he managed to replace that image without needing to access the HTML or JavaScript. Also turns out to be a pretty good way to replace anything with an image.

(more…)

Slider with Sliding Backgrounds

Among the many super nice design features of the Yahoo! Weather app for iOS is the transition between city screens. The background image doesn't just move away as the screen moves from one screen to the next, the background image itself slides. It appears to be hiding some of the "old" screen and revealing more of the "new" screen those closer you have it to being in full view.

Let's try and pull it off on the web.

(more…)

Media Query Change Detection in JavaScript Through CSS Animations

The following is a guest post by Alessandro Vendruscolo. Media queries are relevant to both CSS and JS. The need and desire to manage those in one place is real. There have been some clever ways to do this, like Jeremy Keith's Conditional CSS. But in that case, the onus is on you to test after window state changes. You can get a true listener with MediaQueryList, but then you're maintaining the media queries in both places again. Ah well, I'll let Alessandro explain.

(more…)

Naming Media Queries

It would be pretty cool if we could do this someday in CSS. The best idea for it that I've come across is to define it in a <meta /> tag in the <head></head>. That way (perhaps) CSS could use it and JS could use it. Like window.matchMedia(nameOfMyMediaQuery) or @media (nameOfMyMediaQuery) { }. But since we can't, Sass has our back. Now the question is, how do we name them?

(more…)

Line Clampin’ (Truncating Multiple Line Text)

You want X lines of text. Anything after that, gracefully cut off. That's "line clamping" and it is a perfectly legit desire. When you can count on text being a certain number of lines, you can create stronger and more reliable grids from the elements that contain that text, as well as achieve some symmetric aesthetic harmony.

There are a couple of ways to get it done, none of them spectacular.

(more…)

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