Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Developing a responsive, Retina-friendly site (Part 2) (paulstamatiou.com)
121 points by PStamatiou on March 13, 2013 | hide | past | favorite | 31 comments


I've loved this series, it shows how complex web-design has become but has a considerable amount of actionable information on what the latest libraries/hacks available are.

It's also a bit deflating. Just when you thought the kind of arcane knowledge needed to survive the IE-compatibility-era was over, the explosion of new resolution and screen types have made web dev -- even just the design and display side -- something with considerably more moving parts than I remember from ten years ago.


I feel always a little lost when I read tutorials which use SASSy/LESSy CSS. Illustrating exemples with a preprocessor means lots of web developers won't be able to read you.

Moreover these developers are not in the hype bandwagon (or they would be able to read SASSy/LESSy/whatever fashionable now), so they may need the most the said tutorials.


You should learn one of them. It'll make your life so much easier that it's not even funny. They're also really straightforward (for the most part).

So you know that Sass and Less allow you to nest rules, right? e.g.:

    .foo {
        p {
            // rules go here
        }
    }
translates into .foo p { rules go here }

Here are the examples from the article:

    &:hover { opacity: 1; }
The ampersand simply means 'I am applied in the context of whatever rule I happen to be in'. So, .home { &:hover { } } is equivalent to writing this normal CSS:

    .home:hover {
    }
@include is like #include in C. It literally includes the referenced content in the rules you're writing. That means that

    .home {
        @include bg-size(60px,auto);
    }
is including something that (inferring from the name, here) sets the background size for the element. Given the parameters, it probably expands into:

    .home {
        background-size: 60px auto;
    }
plus another rule for handling 2x images in Webkit.

This is a variable. Nuff said.

    $sprite_url_2x: "http://turbo.paulstamatiou.com/assets/pstam-sprite-v2-@2x.png";
make sense?


Given I don't understand SASS and Less, you seem to have, in each case, replaced some CSS with something which is longer, and less easy to understand.

I am sure these is some extra magic you are not telling us, but given that you are assuming we don't know about SASS and Less, you are obviously missing something important :)


You're actually the one missing something important: complexity.

His examples are simple, meant to give you an idea of how sass/less work on a basic level. But I'm currently working on site that is several thousand lines of CSS, employing enormously complex css structures. Pseudo-selectors are in use everywhere. As are complex gradients, shadows, sprites...

It's imperative to have some sort of organization in your code. Working with really long class names or IDs isn't an option.

For instance, on this project, we have a defined color set of colours. The red we're using is #c03838. The blue is #2767d1. A shadow used throughout the site is 1px 1px 3px rgba(0,0,0,0.2), and one of the gradients (used in a few places) looks like this when written out fully: http://i.imgur.com/YZi3f0B.png

It wouldn't make sense to memorize those values/strings. Not only that, but it would become a pain in the ass to change them in specific places over dozens of iterations if that becomes necessary. Instead, if I define things like $headline-color and $highlight-color, I can refer back to those in my header file, and change them throughout the site simply.

In the case of complex selectors, it becomes vastly more simple. Not only is your style sheet organized analogously to your dom tree, but it's infinitely more flexible, and doesn't require duplicate writing in the case of long chains.

Less/sass are a huge boon to front end development because they help you manage complexity. That won't come through in simple examples, but it should be obvious if you've ever written a stylesheet more than a few hundred lines long.


"Working with really long class names or IDs isn't an option."

How does SASS/LESS solve this? Don't you still need the class names and IDs to hook it up with the DOM?


Yes. My point is that you avoid namespace conflicts.

Say you're building a windows-style scrollbar:

                |-> up arrow button
    scrollbar --|-> track -> drag button
                |-> down arrow button
Rather than having a CSS file (1) full of long, convoluted global class names:

    .scrollbar-frame{}
    .scrollbar-button-up{}
    .scrollbar-button-down{}
    .scrollbar-track{}
    .scroolbar-track-drag-button{}
or (2) full of overly-verbose endless trails (imagine how this gets when you're working with a complex object 5-6 levels deep)

    .scrollbar-frame{}
    .scrollbar-frame > .button-up{}
    .scrollbar-frame > .button-down{}
    .scrollbar-frame > .track{}
    .scrollbar-frame > .track > .drag-button{}

you can do this:

    .scrollbar-frame{
        .button-up{}
        .button-down{}
        .track{
            .drag-button{}
        }
    }
On compilation, you'll end up with a final result somewhat like example 2 -- but you weren't forced to write your first-level selector over and over the whole time. Your code also resembles the structure logic much closer at write time.

It gets better, too. Let's say we wanted to define our buttons in the classic windows 95/98 style -- grey, with a 1px relief border. In the classic CSS style, using example 2 as a pattern, we'd have to do it this way, duplicating our definitions the whole way:

    .scrollbar-frame{}
    .scrollbar-frame > .button-up{
        height: 20px; 
        width: 20px;
        background: #ccc;
        border-top: 1px solid #ddd; 
        border-left: 1px solid #ddd;
        border-bottom: 1px solid #888;
        border-right: 1px solid #888;    
    }
    .scrollbar-frame > .button-down{
        height: 20px;
        width: 20px;
        background: #ccc;
        border-top: 1px solid #ddd; 
        border-left: 1px solid #ddd;
        border-bottom: 1px solid #888;
        border-right: 1px solid #888;
    }
    .scrollbar-frame > .track{}
    .scrollbar-frame > .track > .drag-button{
        width: 20px;
        background: #ccc;
        border-top: 1px solid #ddd; 
        border-left: 1px solid #ddd;
        border-bottom: 1px solid #888;
        border-right: 1px solid #888;    
    }
However, using SASS/LESS, we could define a mixin. Using SASS, here's how you'd achieve the exact same thing:

    //Define a mixin
    @mixin greybtn{
        width: 20px;
        background: #ccc;
        border-top: 1px solid #ddd; 
        border-left: 1px solid #ddd;
        border-bottom: 1px solid #888;
        border-right: 1px solid #888;
    }

    .scrollbar-frame{
        .button-up{
            height: 20px
            @include greybtn; //Include our mixin.
        }
        .button-down{
            height: 20px
            @include greybtn;
        }
        .track{
            .drag-button{
                @include greybtn;
            }
        }
    }

The resultant code will be almost exactly the same, but you just wrote a lot less to get there, and will have an easier time of modifying it in the future. You can see the massive benefit in both speed and organization this allows, especially on large projects.


This is actually a great argument. I'm almost convinced. However, in the second example, wouldn't it be better to just have a .scrollbar-frame > .button with all the styles and then just do class="button up" and class="button down"?


Yes, but this enables it to be reused in other contexts, where the names "up" and "down" would not make much sense, but you would like to have the same border style for some reason.

Plus, you could turn this into a mixin "function", with the actual colors of the states changed depending on where you include it.

So the way he writes it, you could have a green, blue, whatever version of those borders, with the same one line (plus a parameter), whereas in CSS you would have to do:

up-blue, up-red, up-green, down-blue, down-red, down-green etc classes.


For me, the killer argument has always been cases like this:

   a.btn {
   &-primary,
   &-info,
   &-success,
   &-warning,
   &-danger {
   		&, &:link { color: #fff; }
   	}
   }
Where the & is replaced with the previous mark, so it would create a.btn-primary, a.btn-info. You might still argue that you could get close to the amount of characters with vanilla CSS, but as soon as you have to change small bits of this, you end up refactoring a lot of code.

With LESS and SASS, you have a built-in capability to refactor things very quickly.


I'm now going to state something really stupid.

In none of aaronbrethorst's examples were multiple terms put inside a single pair of { }. Now I can see the advantage, as (obviously) when writing CSS it is common to have a lot of repetition of the type this lets you reduce.

Now, I can see the purpose of LESS and SASS. Sometimes when explaining something to someone, the most useful feature can seem so obvious as to not need explaining.


That's because manually indenting text in HN's commenting field is a tedious, error-prone process, and I am a profoundly lazy person. ;)


If you use Firefox, I highly recommend ItsAllText. It lets me right click on a textarea and open the contents with my editor of choice. When I save the file, whatever I wrote is automatically copied back over to the textarea.

Bulk indentation is one of the main reasons I switch over to vim for editing web text.


I don't think he was going for a value pitch, just a brief intro. It's really difficult to judge the value of CSS preprocessors from one-line examples, since as you say they usually end up being longer. You would have to look at larger stylesheets to actually see where they shine. In other words, the benefit from preprocessors isn't constant, it's exponential. You trade off some added complexity for a much greater ability to organize, combine, and maintain the various parts of your stylesheets.


The brevity starts to come in once you begin to use multiple rules inside each nested context, and get into multiple levels of nesting. The point of the @includes (called "mixins") are that they might expand into something much more complicated. Imagine a gradient mixin that expands into all the vendor-specific gradients with the correct syntax.


It's longer for the simple case, declaring and calling a function once is also always longer than simply inline the code.

Nesting rules allow you to turn

  .foo p {
  }
  .foo p a {
  }
  .foo p div {
  }
into

  .foo {
     p {
        a {
        }
        div {
        }
     }
  }
Less duplicate code and more obvious hierarchy.

'&' context reference allows you to turn this.

  .widget a.button { ... }
  .widget a.button:hover { ... }
  .widget a.button:active, .widget a.button:focus { ... }
Into

  .widget a.button {
    ...
    &:hover { ... }
    &:focus, &:active { ... }
  }
Again, less duplication, less code to read/change. More obvious hierarchy.

@includes is like writing function. Which is very useful when you have to write browser-specific style. You can define `round-border` mixin once.

  @mixin round-border($radius) {
     border-radius: $radius;
     -moz-border-radius: $radius;
     -webkit-border-radius: $radius;
  }

  .dialog { 
    @include round-border(10px);
  }
  
  .color-picker { 
    @include round-border(5px);
  }

  .button { 
    @include round-border(3px);
    ...
  }
Is that less clear or harder to maintain than CSS version?


>Given I don't understand SASS and Less, you seem to have, in each case, replaced some CSS with something which is longer, and less easy to understand.

You could say the same objections to anything you don't know. CSS, HTML, JS whatever.

When you try to use it and understand it you will see why its useful. Or, if you still don't find it useful, you will at least have a reason, besides "I don't know it".

I assure it they are very useful. I use LESS.

You can use as little or as much of LESS as you want. A valid CSS file is also valid LESS (just uses 0% of it's features). You can start using some features as you learn it.

For a simple example, in order not to repeat 100 times a color, you can save it as a variable:

@main_color: #ddd;

then you can use it in rules like this:

blockquote { color: @main_color; }

.logo { border: 1px solid @main_color; }

So changing all the colors in a site it's as easy as changing ONE line, not hunting for #ddd; everywhere.

Basically, LESS is to a CSS file, what a CSS file is to setting things directly on the style attribute of each element.

You wouldn't style each element directly on the page, right? You'd use a referenced CSS stylesheet. Well, for the same --or very similar-- reasons, I wouldn't use a mere CSS file anymore.


I'd guess that it's not the actual idea of LESS/SASS that most people don't grok, it's the integration into their deployment workflow.

Since they don't use it every day due to setup woes, they can't easily read it fluently.


It sounds kind of weird, but I'm actually really passionate about CSS pre-processors. Switching to LESS from plain CSS was one of the biggest and clearest productivity improvements I've ever made to my dev toolkit.

I was reluctant to try it as I feel like there are already so many moving configurable layers to my dev stack and all I could think was "I have this nice static css file here - I just include it and everything works" and the only real exposure I had had to LESS/SASS was exactly the same sort of context free dozen lines of mixin code that does something awesome in some blog post just like you are describing (which made it seem much more intimidating than it actually was).

Now here's the real kicker: I didn't realize that I already know how to code css in LESS. Since LESS is a superset of CSS you can take any CSS file (even one from an existing application) and put it through a LESS processor and get back a usable CSS file. This is awesome as it makes it possible to start using LESS in the middle of a project and it makes it very easy to slowly stop doing all of the soul crushing find+replace that takes forever working with CSS as you ramp up with LESS.

I'd really encourage you to give LESS (or SASS or whatever you find fashionable) a try - I think you'll like it. If you get stuck or need help shoot me an email (on my acct page).


Compass' docs' code snippets have little tabs that allow you to switch between the SCSS and Sass syntaxes that I think would be great for people like you that need to see the CSS output. I wonder if anyone's made something like that (possibly with Stylus in addition to LESS), even though I agree with the sibling comment that suggests learning one (I prefer Sass).


This level of complexity for images (1x and 2x) is madness. And the real kicker is, it doesn't even account for the kind of variable zooming people do on their phones, which can result in 1.73x, 2.79x, 4.23x, etc.

I've found it vastly simpler to adopt a much more flexible and simpler approach. Just include single images (not multiple versions), and pick resolutions that are appropriate for the image -- that convey the level of detail the image deserves. And when you up the resolution, knock down the JPEG quality.

Sometimes this means 3x or 4x for bullets or icons mixed in with body text. Sometimes it means 1x for photographs. Sometimes it means 3x for small illustrations and 1.5 for larger ones.

Don't worry about things being pixel-perfect, because pixels don't exist anymore. Just aim for whatever resolution communicates the necessary meaning of each element. Good judgment is your friend.


I realize Paul is doing it for the sake of learning, but that seems like an insane amount of consideration to display and bandwidth.

I remember seeing an article that argued that you should just serve up big images, and that slow cellular data networks scale down and optimize images pretty well already.

Basically it argued that it wasn't worth the trouble. Even with some Googling I can't seem to dig it up.

Thoughts on this, anyone?


I began retina-ifying my website (http://betterexplained.com). I'm serving up the high-res images. Something like a logo should be downloaded once and cached for a long time.

I have a lot of LaTeX-generated images, which is too painful to set using CSS rules. Also, for RSS/email readers, they don't have the full stylesheet available (feed-to-email service), so I want the image dimensions specified via attributes, not CSS.


>Something like a logo should be downloaded once and cached for a long time.

The cache on mobile browsers is tiny (4-85MB), your logo will likely only be cached for that visit. I'm finding sites claiming IOS didn't even have a disk cache for safari until IOS 6? So in that case it is certainly only getting cached for one visit.


Interesting point, thanks for sharing. I might do CSS targeting for site-wide images, and leave the in-post images (i.e., the ones coming via email & rss) with the high-res versions.


Despite the advice in the article, never use an <img> tag with an empty src attribute - it causes the page itself to be requested, which is probably a larger request than just serving up a low res image in the first place.

Otherwise lots of interesting points here, and a lot of thought given to the fine details a lot of us would otherwise skip over. Good work mate


Wicky and I chatted on Twitter -- I think this is only a case for certain older browsers. Haven't seen an issue with anything like this in recent browsers in the last few years


I've done some investigation and you're right, it seems that it's been fixed in the majority of modern desktop browsers. As far as I can tell Chrome, FF, Opera, Safari and IE (9+) have resolved this issue [1][2][3][4]. Can't find any data on mobile browsers, haven't got the patience.

[1] http://www.nczonline.net/blog/2009/11/30/empty-image-src-can...

[2] http://www.nczonline.net/blog/2010/03/16/empty-string-urls-i...

[3] http://www.nczonline.net/blog/2010/07/13/empty-string-urls-b...

[4] https://code.google.com/p/chromium/issues/detail?id=38144


Do people just scale down the 2x icons to create the 1x series or actually change the icons (emphasizing certain aspects in the 1x version)? Based on my experience on the rMBP, it seems as if the icons are actually different.


The people who currently care about retina-friendly graphics tend to be those who have long cared about carefully hand-tweaking every variant-scaled version of every graphic they produce.

But as hi-dpi concerns become more mainstream, I doubt there will as much overlap and we'll see a lot more naive scaling.


I just use SVG for all icons, so I don't have to worry about it. I design them on a low-DPI display and am usually pleasantly surprised when I check in high-DPI.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: