January 07, 2014

A New Website, Part 3

CSS3 and hacks and stuff

CSS is always a pain. Honestly I think that until flexbox arrives, we’re constantly going to be using hacky things for layout. But I thought I’d make a list of all the hacky things I did, and the not-so hacky things that worked awesomely.

###Columns

Here’s a really nice thing: on my about page, I have a list of ‘things I like’. It’s split into 4 columns, which goes down to 2 on smaller widths. I made a SASS mixin for it that automatically handles cross-browser compatibility and fallbacks:

@mixin columns($count: 2, $gap: 20px) {
    .csscolumns & {
        -webkit-column-count: $count;
        -moz-column-count: $count;
        column-count: $count;

        -webkit-column-gap: $gap;
        -moz-column-gap: $gap;
        column-gap: $gap;
    }

    .no-csscolumns & li {
        display: inline;
        line-height: 1.6;
    }

    .no-csscolumns & li:not(:last-child):after {
        content: ',';
    }
}

I use a custom build of modernizr to detect for css3 columns, and then fall back to a comma separated list when it’s not supported. I think it’s pretty great that thanks to the & operator in SASS you can bake surrounding styles into a mixin. So the SASS I end up writing looks something like this:

.columned-list {
    @include columns(4);

    @media screen and (max-width: 960px) {
        @include columns(2);
    }
}

pretty neat.

###absolute centering

The text on the header of my index page, ‘Hi I’m Robert…’ is vertically and horizontally centered within the header div using this trick. It works like a charm except that if you do that, you have to absolutely position everything else in the div that’s not being vertically centered. So I had to center my top nav and my scroll indicator (the three downwards pointing arrows) with absolute positioning and negative margins. Yuck.

The other problem was, since they weren’t in the flow together anymore, if the height of the window got really small the central text and the navigation would overlap. I spent a stupid amount of time trying to figure out a way around this when I realized I could just put a min-height on the header.

###responsive navigation & jQuery

On small screens, the nav turns into a hamburger button trigram for heaven that opens up the rest of the nav above it, in a slideDown menu. This is the only thing I’m using jQuery for because I didn’t want to have to write that animation myself (even though I wrote the scroll animation myself, the one that happens when you click the three arrows). The other problem was that if you clicked that button to show/hide the nav, jQuery would alter its display property inline, which meant that if you made the window big again that property couldn’t be overriden by CSS media queries, meaning the nav would stay hidden.

The solution to this was window.matchMedia, explained very nicely here by Tyler Gaw. I wanted an event listener type pattern beause I didn’t want to have to check on every window.resize, so this was perfect.

###Safari being a dick

I don’t know if it’s just my computer or what, or Mountain Lion (which I only recently and reluctantly upgraded to), but Safari just couldn’t handle my homepage for some reason. Although my z-indexes were correct, the canvas animation was rendering on top of everything else even as you scrolled down. Even more frustrating was the fact that mousing over a title and triggering a CSS transition popped the layers back into their right place. Then you would refresh, and the problem would sometimes be back, sometimes not.

I couldn’t find a straight answer to why this was happening, but I did realize that the screen just needed to be repainted, so I found this solution that said that appending an empty <style> tag and then removing it would do the trick. So I do that on every scroll event. (I tried just doing it once, but that didn’t work consistently for some reason). I also wish I could limit it to just safari, but right now I think the tradeoff for having to write sniffing code vs just having that check everywhere isn’t worth it.

@RobertVinluan