Styling input placeholders with CSS

HTML5 and placeholders

HTML5 gave us many wonderful things. And in this case, the grass was really greener on the other side. After paddling our small HTML boat over to the grand island of HTML5 we set up camp and decided to stay, for life (or until some other even cooler island - HTML6 anyone!? - floats by).

One of many wonderful things was that we could toss out all those onfocus and onblur JavaScript combos that toggled some informative text in forms before they were filled in. Sure we had labels, and even lines of help text, but sometimes a placeholder was just right for UX and overall design (and semantics).

Old school versus new school

Remember the horrors of old? Let’s take a trip down memory lane. This is how I used to “fake” placeholders with JavaScript (true story) in the age when dragons still roamed the lands and everyone travelled by horse (a few years ago ... trust me):

<input type="text" name="mahfieldyo"
  value="A brilliant placeholder"
  onfocus="if (this.value=='A brilliant placeholder') this.value='';"
  onblur="if (this.value=='') this.value='A brilliant placeholder';"
Screen Shot 2016-06-29 at 09.39.58.png
This is how my old school placeholder looked
<input type="text" name="mahfieldyo"
  placeholder="A brilliant placeholder indeed">
Screen Shot 2016-06-29 at 09.39.53.png
New school is "same same but different" (much better)

Your design task

So the story goes like this - you get a design, from a designer. And as we all know, they sometimes tend to design impossible things, things not meant for the web (damn you Photoshop). But things progress, and with time we suddenly have new super powers in CSS. Remember all those round corners about 6-7 years ago that were almost impossible before CSS3 (hello 3x3 cell tables with images in each corner)?

The design versus what you can build.

You need a black semi-transparent (50%) background with a white colored text (opaque). Easy. You try the CSS' color property on the input field. Doesn't work. The placeholder will default to gray (a washed out white color). But you want it to be clear white, just like when you type text in there. You give up and cry a little bit. Fear no more. The solution is not far away!

You’d think that this really is something that is impossible. The big browser vendors sat down and said “Our way or the highway, son”, and we be all like “Yes, ok Sir, sorry for bothering you”.

But no, this is not the case this time. There is no Hersey highway you need to take. Let me show you how magically easy you can change the style of a placeholder text. Let pseudo elements (and classes) lead the way to glory and fame. But also, let vendor specific implementations hurl shots at you along the way (rest assured, we will reach the other side alive).

The code

Our new friends to get acquainted with are: ::-webkit-input-placeholder, :-moz-placeholder, ::-moz-placeholder and :-ms-input-placeholder.

To mix things up for us, they interchange between using one colon (pseudo-class) and two colons (pseudo-element) in the beginning. Because … why not?

Chrome, Safari, Opera and even Edge will listen for the webkit vendor tag, older IE (10+) for the ms vendor tag, and Firefox for the moz vendor tag. Easy peasy. So with these “tools” our design will work everywhere *.
* Not really everywhere, but close enough for me to say “everywhere” without being called a complete liar. Who cares about IE9, Firefox 3, and other legacy browsers anyways? Oh, you do?! Then I feel sorry for you (but also laughing a little bit at the same time, like when people walk into a lamp post, or they slip on a banana peel).

Let’s look at them in action. This here is them magic lines to fix it all:

::-webkit-input-placeholder {
	color: white;
:-moz-placeholder {
	color: white;
	opacity: 1;
::-moz-placeholder {
	color: white;
	opacity: 1;
:-ms-input-placeholder {
	color: white;

Not bad. That's it. Just copy pasta and give it a taste!

There are some details to explain though. Keep reading.

Vendor specifics and pitfalls

Firefox has different implementations of this spread throughout their versions, hence the almost duplicate definitions with “:” and “::” (double-colon is the latest and greatest implementation).

A catch with this code is that you cannot refactor these into one joined group in CSS, because if one browser doesn’t understand all of the lines it will ignore all of the rules in it, even the lines it does understand. So you must go for all four of them as separate groups, like in my example. Hey, don’t shoot the messenger!

Also, Mozilla’s implementation lowers the opacity of the text, so you need to “reset” it manually to get it to look just right (with opacity: 1;). After that, you’re good to go.

And of course you can be more specific than that and only change placeholder design on specific fields by prepending these pseudo classes with the class name of your choice.

Want more?

Read this brilliant Stack Overflow answer for more details about vendor support and such.

Need more tricks to fuel that CSS fire of yours? Check out how you can override that ugly yellow default background on pre-filled input fields in Chrome.

We’ve explored the deep dungeons of CSS before and found that we can access almost anything you see in your browser and shape it to your liking. But placeholder text in forms, that can’t possibly be styled, right? Right! … wrooong! Let me show you how to use CSS to make your placeholders look pretty again.

Continue reading »


Beautify your Form with Material Design

“Once upon a time there was an Ugly Form. Every day it would look at beautiful forms residing peacefully on the endless pastures of the Internet and sigh with envy.

Don’t I deserve my share of HTML happiness?’ the Form thought.  ‘Why do users shriek in disgust every time they see me? Why do they look terrified (and sometimes cry) when filling out my fields? And why the hell do they wash their hands after clicking my flabby lifeless buttons?””

Every time I would tell this amazing fairytale to my kids before their bedtime, they’d ask me: “Daddy, but why can’t the Ugly Form be happy too? Sure, it looks like HTML got diarrhea and pooped out a pile of colorless Lego bricks, but maybe there’s a chance for it in our cruel world?

And one day I finally decided to play the Fairy Godmother to the Ugly Form and help it turn into the Kim Kardashian of forms overnight (with zero plastic surgery expenses, mind you). After some thorough research I picked Material Design Lite (MDL) as my magic wand and that’s the only thing you will need, too.

I'll get a bit ahead of myself and show you right away what will be the end result of what we're going to do in this article.  


Looks modern and professional, right? But it hasn't always looked like that. In fact, I wouldn't dare to show you how this form initially looked if it wasn't for the sake of this article.

Anyway, let's get to the process. To begin with, we need a web page with an ugly form. I assume you already have it, but if not - just create one and experiment with it. For this article I created a job application form for an imaginary company hiring IT specialists, see below:


The page has some basic styling, mostly to add some padding to controls in the form, but nothing fancy. It’s totally fine if your page is already using some CSS classes. But be aware that they may cause conflicts with the MDL stylesheets, so you might want to tweak the code and remove the old classes (you can do that dynamically using the Javascript code below, too).

When you open that page in a browser, it should look something like this:

One Ugly Form

This form has some basic text input fields, a textarea, a table, several fieldsets with checkboxes, radio buttons and a list of bullet items. And the buttons, of course.

When I saw the ugly creature I just built with my own two hands I was like (in heavy Austrian accent): “YOU ARE ONE UGLY MOTHE**UCKER…”.

Without further ado, let’s rush to the uneasy task of turning this freak of HTML nature into something worth showing to your boss before asking for a pay raise.

First thing we need to do is add external references to the MDL’s js-library and CSS inside the <head> section of your webpage:

<!-- MDL references -->

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

<link rel="stylesheet" href=“https://code.getmdl.io/1.1.3/material.indigo-pink.min.css">

<link rel="stylesheet" href=“https://rawgit.com/MEYVN-digital/mdl-selectfield/master/mdl-selectfield.min.css">

<script defer src="https://code.getmdl.io/1.1.3/material.min.js"></script>

<script defer src="https://rawgit.com/MEYVN-digital/mdl-selectfield/master/mdl-selectfield.min.js"></script>

Alternatively, you can download the MDL package, host it on your own server and reference that instead.

Note name of the CSS file: material.indigo-pink.min.css. The “indigo-pink” part defines primary and accent colors your controls will be using. There are plenty of colors to chose from, but I picked “indigo” because it sounds mysterious and “pink” because everything beautiful is pink (for example, unicorns and €50 bills).

Now let’s create some magic. We need to write javascript code that will loop through controls on the page and apply MDL styles to them. Copy the piece of the code below and paste it inside the <head> of your page, right after the references section:


Look at the code above.

There’s a method called materializeControls which will be called in window’s onload event handler, when the DOM is in place. materializeControls calls another method called materializeTextInputs, which loops through all text inputs and textareas on the page and assigns required MDL CSS classes to them, their labels and their parent divs.

NB! In order for Material guidelines to be entirely fulfilled, each input control must be properly wrapped inside a parent div along with its label. The code will not fail if it’s not the case but "you may not be 100% satisfied with the result", as my hairdresser used to say before I had given up getting haircuts.

When you refresh the page after adding this piece of code, you will see some amazing transitions:

Materialized text inputs

Note how the first three text inputs on the left and the textarea on the right are now rendered according to the Material guidelines with more air around them, labels inside placeholders and nice on-focus highlighting.

By now you are supposed to be completely hooked, like a housewife addicted to Candy Crush, and cry for more.

We will stick to the same algorithm for other controls as well.


Add a new method called materializeSelects that will basically use the same formula as materializeTextInputs - going through select controls and applying MDL styles to them.


The only manual thing we will have to do here is add class “mdl-selectfield—floating-label” to the wrapping div of the select element. This will make sure that a dropdown’s label is shown above the control once a value is selected.

<div class="mdl-selectfield--floating-label">


<select name="education">



Refresh the page to get another injection of pure magic:

Materialized dropdown

Radio buttons

The code for radio buttons is a bit different because they are wrapped inside their labels (so that a mouse click on a label would select the button), but the principle is the same. Note how we apply “mdl-js-ripple-effect” class to radio buttons’ labels to achieve, well, ripple effect. You don’t have to do that but it adds an extra cool touch to user interaction with the elements.


Materialized radio buttons


Exactly the same principle here as with radio buttons (yes, you can use the same method with arguments):


Materialized checkboxes



Materialized table


For lists (<ul> element) we will perform a little trick. To liven up the list of offices we will replace the bullet character with a “home” icon from the huge library of Material icons.


Note how when browsing through <li> elements inside each <ul> we inject an icon before the list item’s text and then wrap both of them with a <span>:

liEl.innerHTML = "<span class='mdl-list__item-primary-content'>" +
                  "<i class='material-icons mdl-list__item-icon'>home</i>" +
                  liEl.innerText + "</span>";

In order to be able to use Material icons on your page, you need to include a reference to their font family from the Google site, but we have already done it: 

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

After that you can render any icon from the Material library like this (we used “home” as an icon Id):

<i class=“material-icons"><icon Id></i>

And that’s how our new list will look now:

Materialized list



There are many different styles and effects that can be applied to buttons; you can read about it on the MDL site. We used the same “mdl-js-ripple-effect” class to get the ripple effect whenever a button is clicked and “mdl-button—colored" class to have them colored in the primary color of our selected scheme (remember indigo?). If you replace the latter with “mdl-button—accent” the buttons will be in accent color (in our case - pink).

Materialized buttons


Believe it or not, but we’re done. Using almost no CSS and only basic knowledge of Javascript, we turned our ugly duckling into a beautiful indigo-pink-ish swan. We could have refactored our Javascript code a little to have just one pass through all elements on the page and then dispatch processing to other methods based on element type, which would of course be much better performance-wise, but here I tried to visualize “converting” controls type by type.

And this is how our form looks after our changes:

Screen Shot 2016-06-23 at 00.26.18.png
Materialized form

For even better effect I will show you the same form “before” and “after”, side by side:

Screen Shot 2016-06-23 at 00.10.16.png
The Ugly Form before and after the changes

And here's the final source code of our now beautiful form:


I hope that this article will help you to take your first steps into the beautiful land of Material Design. It’s not as scary or complicated as you may think and along the way you might even help a page or two become better versions of themselves without giving it too much effort. After all, each of us had our encounter with an ugly form even if we chose to keep it a secret.

Material Design is a hot topic nowadays. There are many who have heard of it but not so many used its guidelines in their work. It looks sexy and stuff but how do you inject all that beauty into your website? This article will explain how to apply Material Design look and feel to forms on your existing web pages using basic knowledge of JavaScript and a 3rd-party library called Material Design Lite.

Continue reading »


Remove forced yellow input background in Chrome

You'd think this is easy as pie to override:

"Just set background-color with an !important after" - Random Dude (or Dudette).

But no, life aint that sweet this time. This is a known bug in Chrome, that they have been having problems with since 2008! The issue had activity no later than March 2014 (as of writing) but apparently it's more complicated than just turning off a switch and allow web designers and developers to override the color themselves.

In my opinion I should be able to set the !important after the background-color attribute in CSS and get the respect that this deserves from the browser.

input {
     background-color: red !important;

No workey =( And no, setting autocomplete="off" on the entire form is not a solution, it's a work-around just skipping the problem by losing functionality and should only be used as a last resort.

Googling around, I found that Webkit browsers actually have their own element state on input fields. It's called -webkit-autofill. How sweet. Since I only have this problem in Chrome I don't mind using some vendor prefixing for just this specific case.

input:-webkit-autofill {
    background-color: red !important;

Now it should work! Nope, still nothing. And there's the bug. Chrome forces that pale old yellow so hard on it's pre-filled forms that it can't be overridden. At least not by trying to set the background-color.

Let's step up our game and think outside the box. By setting a "inset" box shadow for Webkit, and fill the entire input, we might solve the problem. With just one big solid color we would have the same effect as with a background color.

input:-webkit-autofill {
    -webkit-box-shadow: 0 0 0px 1000px white inset;

Yes, finally! That actually did the trick. And since this bug only affects Chrome, adding the vendor prefix isn't a problem for compatibility either.

Now, one could argue that you shouldn't override the only indication to the user that a form has been auto-filled (except the presence of the text itself). I can agree. You maybe shouldn't do this for an entire form where it can be difficult for a user to know what has been pre-filled by you - the developer - and by the browser, or by the user himself for that matter. But for my case, a simple login screen with username and password, you pretty much understand that if there is text in the inputs, it has been pre-filled by the browser. Also the design is pretty important here as the input fields are large and floating in the middle of a giant background image. When those inputs lit up in pale yellow something broke inside the esthetic part of my brain. And for sure if I didn't fix that, it would be something on the "fix-list" I would get from the designer or the client before launch. So why not beat them to it?

Further, the text-color is also forced to black. It can only be overridden by setting a forced vendor prefix attribute: -webkit-text-fill-color

-webkit-text-fill-color: red !important;

If you need to have fancy hover and/or focus-effects, then you can play around with these Chrome-specific goodies:


However if you desperately need transparent background color you're doomed. You need a solid color. So in that case I would suggest going with turning the autocomplete off on the form completely if the pale yellow is unbearable.

If you allow your browser to remember what you write into forms it will pre-fill these forms when visiting again. That's very convenient. But Chrome forces a pale yellow background on all these input elements, likely messing up your design. And that background color cannot be overridden ... or can it?

Continue reading »


Fluid layouts done right, with Flexbox

How it used to be

Did any of you develop in the era of using tables for position and structuring your design? It worked, and we got pretty good at it. But it bloated our markup, was overly complicated, and very wrong in regards of semantics and accessibility. It basically got the job done, but nothing more than that. It did everything else wrong.

With the magic of float:left and float:right we could do the same as we did with tables. We were saved! Or so we thought. After transitioning from tables to floats we still missed a lot of the benefits the table elements gave us. Things like equal height columns, and vertical alignment, proved to be something other than a walk in the park when it came to floating.

Floating divs and other elements is more correct semantically, because the style and layout is moved to your stylesheet. It’s more accessible. But for the developer it got a bit too tricky sometimes, as mentioned. A plethora of CSS-hacks, tricks, and quirks, popped up. To do simple things like fixed footer and equal column height you had to think outside the box; switching out display: inline to display: table-cell, wrapping things in extra elements, adjust positioning, faking things, and so on.

What is the flexible box model

The flexible box model is like the other box models. It has content, padding, margin, border, and outline. It works on the semantic you usually use, like the good old div, or the new guys in town: article, aside, header, etc.

When you in your CSS say that an element is of the flexible box model type, that element starts to get almost super powers. As the name implies this models main advantage is its flexible nature. Everything inside a flexbox will be treated as flex children. These kids can easily and dynamically take the same height as the other kids, add liquid space between them, occupy all the space that is available after another element took X pixels, vertical align any block, reorder the visual presentation apart from the semantic one, etc.

By setting display: flex; on your wrapping element, you now have a completely different way of working with positioning and layout. You don’t even need to set margins on these kids because the flexible box model supports dynamic justify, like space-between that just adds space between the elements from the available unused space.

How is flexbox better?

Working with the web has always been perhaps a more growing and evolving business than others. As we advanced in the field of design and UX, we found existing techniques and used/combined them to produce what we needed. As was the case with Tables, a markup not meant for design. Then came floats, which was more meant for design. But as our designs kept evolving even floats started to fail us.

Flexbox is more or less architected from the ground up to actually be the supreme solver of all things positioning and flexibility. With a “tool” that’s from the ground up made to solve all these things, we get a code that is much easier to maintain, more readable, less dependent, and more future proof. During the transition period we will of course have a lot of people that haven’t learned flexbox yet, but in the past we’ve seen the community taking a big part in educating the masses.

We can’t but applaud the fact that we can potentially drop a few JS-plugins and polyfills as flexbox gets better support. And our semantics and the logic of our stylesheet improve. Equal height on divs (columns) - no problem. Reorder DOM-elements when displaying them - no problem. Vertical alignment - no problem. Sticky footer - no problem. Not all of them need extra JS, but we need to produce extra CSS to get it working, and adding more to our code at a later stage might turn really ugly.

However, no matter how sweet this new technology is, we do have to wrestle the ever present browser compatibility issues. But on the bright side, conformance to W3C-standard is pretty high for flexbox in most modern browsers, and non-supporting browsers see a steady decrease on its user base.

Check out html5rocks.com for more information on flexbox performance.

Browser compatibility

Something that’s a bit unique with the flexbox-standard is that it has been implemented twice. We had an intermediate implementation in most modern browsers, during flexbox working draft stage at W3C. And two years later the working draft became candidate recommendation, with major changes to the standard. So, the browsers implemented it all over again, leaving the developers with two different supports for flexbox - yeey!

Other than that, Chrome, Firefox, and Opera have had good support for some time now (from 2012). With IE catching up with the support in their 11th version. IE10 supports its own hybrid between the new standard and the old one. And older browsers (Firefox, Opera and Webkit-based ones) support either the old standard (post 2009), or none (pre 2009). Of course some with vendor prefixes sprinkled over the code based on browser modell.

Check out Can I Use for more on browser compatibility as it’s kind of a big mess. For modern browsers you should get a long way using flexbox standard syntax with the -webkit- vendor prefix added in. flex-wrap and flex-flow (flow is just a short-hand for many other flex-commands that do work) will give you the most problems, since they’re not supported in modern Firefox (as of January 2014). And if IE8 and IE9 are important to you, you’re kind of out of luck. But a polyfill called Flexie JS can be used to make the old 2009-syntax work on older browsers. For the modern standard, the world has yet to invent a polyfill.

If you are eager to start using flexbox now, you can try FlexboxDetective developed here at Enonic. It lets you target browsers with flexbox support by adding classes to the html-element. This way you can provide fallbacks for older browsers. Much like how Modernizer works, just slimmed down as much as possible to just check different kind of Flexbox support.


Fixed and fluid width columns

flex-grow, flex-shrink and flex-auto determine how to fill the remaining space along the main axis.

Fixed width columns - 1
Fixed width columns - 2

To be replaced

To be replaced

Although all items have width set to 100px, only the three first items will be flexible. The last item has both flex-grow and flex-shrink set to 0.

Equal height

By setting item-align to stretch, we tell the flex items to all take the height of the tallest item in the same row. Note that height, min-height and max-height are still respected. Item two is still shorter than the other items since height is set to 120px. 

Equal height example

To be replaced

Advanced example

In Flexboxshopping (jsbin) we have used flexbox to do several things:

  • The header, nav, main and footer element are all flex items with flex-direction set to column.
  • The menu is flexbox.
  • Flexbox is used to give the right column the same height as the element wrapping all the products. The right column also has a fixed width while the product wrapper fills the rest of the width.
  • All the products are flex items with min-width and max-width.
  • The elements inside the product box are flex items. This lets us align the “More information” link to the bottom.

Tip: Try resizing the example to experience flexbox in action.

Note: This example will not work properly in browsers that don’t support the flex-wrap property (Firefox 27 and below). For browsers who don’t support flexbox it will obviously not work at all.

Flexbox CSS properties

The flexible box model uses various properties to control the layout with a containing element and its child elements. Some of the CSS properties are applied to the flex container and others to the flex items.

Flex container properties

display: flex | inline-flex;

A flex container is defined with the display property.  Using the value inline-flex causes the container itself to be rendered inline, and using flex will render the container as a block element. CSS columns do not have any effect on a flex container.

flex-direction: row | row-reverse | column | column-reverse;

The default value is row which will align the flex items horizontally, ordered left to right while column will arrange them vertically, top to bottom. Using either of the reverse values will simply change the order in case you ever need right-to-left or bottom-to-top. When the main axis of the container is horizontal, the cross axis is vertical. The flex-direction determines how many of the other flex properties behave, so the following examples will assume the default horizontal axis unless stated otherwise.

flex-wrap: nowrap | wrap | wrap-reverse;

The default here is nowrap which will place the flex items in a single line. If set to wrap then flex items will wrap to the next line along the cross axis. This does not yet work in Firefox so don’t plan on using multi-line any time soon.

flex-flow: [flex-direction] || [flex-wrap];

This is the shorthand way of setting flex-direction and flex-wrap in the same line of CSS.

justify-content: flex-start | flex-end | center | space-between | space-around

This defines how flex items will be aligned along the main axis. The default is flex-start, so when the main axis is horizontal, the flex items will start on the left. Using flex-end will align the items to the right and center will center them. Using space-between will put an equal amount of space between the flex items and space-around will put space between each item. Of course this is only useful when the combined width of the flex items is less than the width of the container.

align-items: flex-start | flex-end | center | baseline | stretch

This is very similar to the justify-content property but for the cross axis. When the main axis is horizontal, the flex-start and flex-end values will align flex items with the top or bottom of the container respectively. Using center will align them in the middle and baseline aligns them according to the text baseline. The default is stretch, which will make all the flex items the same height as the container unless they have a height or max-height specified.

align-content: flex-start | flex-end | center | space-between | space-around | stretch

This is pretty much the same as justify-content except that it works on the cross axis and only when there is more than one line of flex items.

Flex item properties

The properties float, clear and vertical-align have no effect on flex items.

order: [integer]

If you want to change the default document order of your flex items, simply specify the position by number.

flex-grow: [number]

The number value specifies the proportion that this flex item should grow to take up available space in the container. The default is 0 so this won’t take up extra space. If each flex item has this set to 1 then they will all be the same height as the tallest. If one is set to 3 and the others are set to 1 then that flex item will be three times taller. Of course flex-grow will affect the width rather than height when the main axis is vertical.

flex-shrink: [number]

This is the opposite of grow. The default is 1.

flex-basis: [length] | auto

The default size of a flex item can be specified before the remaining space is distributed. The default is auto.

flex: none | [flex-grow, flex-shrink, flex-basis];

This is shorthand for flex-grow, flex-shrink, and flex-basis. Only the first parameter is required and the default is 0 1 auto.

align-self: auto | flex-start | flex-end | center | baseline | stretch;

This is for aligning individual flex items and overrides the align-items property.

In a world of darkness, where no CSS standard ruled the world – one man had one destiny: To kill all nasty CSS hacks. Having defeated tables in an epic battle with divs, our hero witnessed a new enemy rise from the ashes. Known as floats, this ruthless enemy left a flaming trail of devastation whenever the people called upon him. But our hero had a secret weapon: the weapon of flex.

Continue reading »


Animate your webpage with the scrollbar

What is Skrollr

Skrollr is a JavaScript-plugin that helps you animate objects on your webpage as you scroll. A lot of people call it "Parallaxing", but that is just one of many effects you can add to your site. There are plenty of these kind of plugins out there, but from my light testing I found Skrollr to be the most lightweight and straight-to-the point of what I needed.

You just include Skrollr and then append data-attributes in your HTML, this will create animation keypoints at different scroll positions. Then tweak your animations with normal CSS-styles while Skrollr works the magic. It doesn’t even need jQuery, so it’s a very quick load.

However, I’ve found Skrollr - as well as many other plugins - totally missing a "Getting started guide". So you’re kind of left at looking up the source to get started, or digging through the source of some examples, and that is absolutely not for everyone. I thought this guide might help you get started with it, with some basic setup and examples. It really is very simple!

To see a demo of some of the possibilities we have with Skrollr, check this link:


Download and "Install"

First things first. Let’s download Skrollr, which isn’t such an intuitive task that you might think. Mainly because there is no download. You have to go to the projects Github-page, and then find the correct minified JavaScript-file, then select all code and manually create this file on your own with that code.

The latest files on Github are also not the greatest as they're work in progress. So find version 0.5.14, which is the stable release this text was based upon. You can find a link to the correct version in the projects main readme-file.

Now open up the "Dist"-folder, and then open the first file in there - " skrollr.min.js ". There you go! Just place it with your HTML and CSS-files and include it the bottom of your page.

Starting up

Create the basic structure of this test case in a folder on your computer. Let’s call it "skrollr". Create a "index.html" in there, and a "style.css". You also need to place the minified Skrollr-code in there. You are of course free to name and place the files wherever you’d like, but my example code will use this structure.

Open your newly created html-file and paste this basic structure in. The only important parts are that you include Skrollr and a CSS-file. But let this serve as a quick start:


With this code you have all you need to start. We will place a few div-tags in here, and a init-script. And we will create some styles. But let’s get that init-script in place so Skrollr get’s loaded (adding the script-tag isn’t enough).

Just paste this small JavaScript init-snippet in the empty script-block near the end of your html-file.

// Start Skrollr
window.onload = function() {
        forceHeight: false

The line skrollr.init is the important one, surrounded by a simple onload-check so that we don’t start manipulating the DOM before it’s finalized. In this example we can see a setting being sent in with the init-setting, forceHeight, set to false. The default is true, so you could just remove the setting altogether if you’d like to change it. What forceHeight does is to make sure that if you try and animate something beyond the total height of your html body, Skrollr will force an increase on the height to allow you to enjoy the full animation. I just included this setting this time to show you how basic settings works, we don’t really need forceHeight for this example to work.

First basic demo

Almost done! Nah, not really. But let’s get going with things you already know - HTML and CSS. My idea for this example to get you up and running in a quick and easy enough way is to simple have three tall blocks stacked on top of each other that we’ll scroll by and see some kind of different animation on each of them.


With this markup (we will come back to the other examples/blocks later) we can move on to our CSS:

/* General */
body, html {
    height: 100%;
    padding: 0;
    margin: 0;
.block {
    height: 100%;
    box-sizing: border-box; /* One of my CSS3-favourites */

/* Specifics */
#block1 {
    background-color: black;
    color: white;
    padding: 20px;
    #block1 p {
        width: 200px;
        line-height: 200%;
        margin-top: 400px;

We just give all the blocks some height, namely the height of your current viewport on the browser. We also force the body-tag to be at least one viewport tall. At last we give some simple style to the top block and it’s text, like color and spacing.

Now, if you take the html-page for a test spin, you should be able to see a big black block of fullscreen background, and some white text. Also make sure you get no weird errors.

But scrolling doesn’t do anything!? OMG! But don’t worry, you just need to write thousands of lines of JavaScript to move the p-tag ... Nah, just kidding. We just need two small attributes added to our html! I kid you not, check this out:


Save and retry, it should perform magic right before your eyes as you scroll downwards (and then reversing when you go back up again).

The data attributes are all that you need to add to trigger Skrollr. Skrollr will automagically animate any CSS you place between your start and stop positions.

data-start is the starting point of your entire page, the absolute top, your page’s y-axis = 0.

data-500-start is the end and triggers 500 pixels from the very top (start) of the page.

You could change this around to test and see how it works. Skrollr just animates your CSS from the closest to the top down to the furthest from the top - from padding-left:20px; to padding-left:400px; the more you scroll down the page.

Important to note is that you must specify some CSS in each data-attribute, Skrollr won’t read anything from your CSS-file.

Change this CSS around a bit to experiment with your animation. It’s really nice and easy. Almost no new syntax to learn and remember, isn’t that sweet?!


Now you know the basics of how this works. Let’s do a couple of more examples which will introduce a few more Skrollr-goodies.

Next task is to animate multiple attributes, at the same time! And we will also stack two animations after another by adding more data-tags. Don’t sweat, this is also easy!

This time we will not manipulate anything on the main block, so create a new div inside of the "block2" div with these attributes:


That’s all! This will animate a 100x100 little red block up to 300x300, then slide it from the top of the containing block down 300 pixels - following the screen as it scrolls.

Let’s analyse this new code we’ve added:

data-top is new, but it behaves very similar to data-start with the difference that data-start fires at the absolute top of the document while data-top fires when the top of that specific block hits the top of the viewport.

data-600-top By specifying a number of pixels before the "top" setting we offset the start with that number of pixels. Here we start the animation 600 pixels before this object reaches the top of the current viewport.

You might have already figured this out, but data-600-top fires before data-300-top, which in turn fires before data-top. So it almost fires backwards to what you would expect, until you get used to this. Stringing many trigger-points together like this let’s you change the animation for the same object at many different scroll positions. You could add as many as you’d like, but try and not go totally nuts about it.

A more advanced example

Now let’s raise the bar even further for our final task. We’re gonna animate three different objects - at the same time, at different trigger points! One block will slide in from off-screen and then get larger, another will change color, and a third block of text will come sliding up from invisibility.


I’m just assuming that you can figure out all of these animation steps, at least good enough so that nothing in there is confusing. The "hsla"-color is explained a bit more in the CSS, and you can look it up on - http://www.css3.info/preview/hsla/ - if you’re unfamiliar with it. Skrollr makes it very easy to animate color changes when we use the hsl(a) or rgb(a) syntax. Skrollr cannot animate color as strings, like "red" to "blue", or hex-values like "#000" to "#f3f904", so you need to get your hsl/rgb-skills straight right away.

Let’s do a few additions to the CSS-file before testing this out:

#block3 {
    background-color: #bbb;
    #block3 div {
        float: left;
        height: 50px;
    #block3 div:nth-child(1) {
        width: 100px;
        background-color: hsla(255,70%,100%,0.9);
        /* HSLA: Hue, Saturation%, Light%, Alpha (Opacity) */
    #block3 div:nth-child(2) {
        width: 200px;
        background-color: hsla(200,70%,100%,0.1);
        border: 5px solid black;
    #block3 p {
        padding-top: 400px;
        opacity: 0;
        width: 200px;
        line-height: 200%;

Nothing extra fancy here, except the use of the CSS-selector nth-child to select the first div and the second div without giving them unnecessary id tags in the markup. And as I said before, if you’re not familiar with the hsla-coloring in CSS3 you should check that up. Basically, this CSS just gives some color and shape to the two blocks and the text. You should test the effects out.

What’s next?

There’s a lot more to test and learn with Skrollr, but now that I have got you started I leave that task to you. data-end, data-center, data-bottom, and data--100-top (for when a object is 100 pixels with it’s top above the viewport) are some other cool triggers you can try out. Also easing of animations - "padding[swing]:10px;" - should be checked out as there are a few methods to choose from.

And of course you shouldn’t miss trying to make your own parallaxing background-demo. Just add three divs, position them absolute on top of each other, make them cover the screen, set a PNG-background with a lot of transparency on each, then make them reposition these backgrounds with background position at different speeds (higher start-stop trigger difference = higher speed) as you scroll.

Be aware of

All is not all good in the world of scrolling and animations though. I’ve discovered that animating large images - especially with animated text on top of it - gives a very choppy experience. And with scroll-triggered animations, you must always keep in mind that the user can scroll very fast, or very slow, which drastically changes the experience. So scroll-triggered animation isn’t perfect for everything.

Also, when the page has loaded and Skrollr has initiated, it will take the first trigger-point for each object and apply that CSS as inline style. If your stylesheet differs from this, you will get a loading experience where the objects on the page looks like they hop around as the Skrollr-style overrides your stylesheet.

Skrollr has a special plugin for mobile, running normal Skrollr on mobile doesn’t work very well. However, Responsive animation takes some extra effort to get working smooth since most triggers use pixels. You can bypass that by only triggering animations on data-top and dynamic values like percentage. You could also create trigger objects in the markup that with their unique id value and the data-anchor-target helps trigger animations.

Reading more

For the offical documentation you should check this link: https://github.com/Prinzhorn/skrollr/tree/0.5.14#documentation

Some examples

The main example-page by the plugin author:

A collection of different examples:

Article teaching you to animate images, including drawing along a SVG path:

A Nettuts+ article about beginning with Skrollr:

Some pages that use Skrollr

Subtle effects to spice up an article:

Heavy use of image-swapping to create 3D-like effects:

Entire source HTML


Entire source CSS

/* General */
body, html {
    height: 100%;
    padding: 0;
    margin: 0;

.block {
    height: 100%;
    box-sizing: border-box; /* One of my CSS3-favourites */

/* Specifics */
#block1 {
    background-color: black;
    color: white;
    padding: 20px;
    #block1 p {
        width: 200px;
        line-height: 200%;
        margin-top: 400px;

#block3 {
    background-color: #bbb;
    #block3 div {
        float: left;
        height: 50px;
    #block3 div:nth-child(1) {
        width: 100px;
        background-color: hsla(255,70%,100%,0.9);
        /* HSLA: Hue, Saturation%, Light%, Alpha (Opacity) */
    #block3 div:nth-child(2) {
        width: 200px;
        background-color: hsla(200,80%,100%,0.8);
        border: 5px solid black;
    #block3 p {
        width: 200px;
        line-height: 200%;

Entire source JavaScript

None needed - woop woop!

Ever scrolled down a website and been amazed that objects doesn't behave like you expect them to? Instead of flowing static content upwards on the screen as we scroll we can now easily animate them in any way. Fly text sideways, zoom in images, fade out objects, and more!

Continue reading »