Oh lordy

in code

Dealing with a WordPress developer

The GPL is apparently all well and good until it comes to your own license obligations.


These are the things I do to trash talk my girlfriend

in random

A GIF of a sandworm eating a cupcake

I couldn’t tell you how the crap this started, but suddenly trash talk about cupcakes is flying thick and fast on Facebook and I’ve been challenged to a cupcake-off at the Iveagh Gardens this summer.

I am so fucked.


Overly-dramatic Mark

in me

Dramatic Mark up in Corrib Village

Props to Eadaoin for the great shot. :D We went up to Dangan yesterday, but the weather was dull, the trees were barely in bloom and there was nothing neither of hadn’t photographed in better light. A shower caught us at Corrib Village, so we stopped in by the boat shed, and Eadaoin shot this with her phone after the rain passed.

I screwed with this in Photoshop: perspective (keystone) correction, bleach bypass, a second black and white layer, over-sharpening of the shed and lots of dodging and burning to make the carved graffiti stand out.


Dynamic-ish CSS spritesheets

in code

CSS spritesheets are cool, even if their use is hacky as hell. You can drastically lower the load time of a site with a little prep work, but did I mention their use is hacky as hell? A sprite sheet works by showing a portion of a bigger image instead of downloading many smaller images. In this case I want to show social icons. Rather than seventeen different service icons in separate 40kb 300×300 PNG file, I added all of them to one 12 kb 600×300 SVG file.

My problem is the hacky part of a spritesheet. Assume you don’t know just what a sprite sheet is for a moment. Envision an image, 200 pixel wide by 100 high. The left part of the image is a Facebook icon taking up 100 by 100 pixels, and the right size is a Twitter icon taking up 100 by 100 pixels. My only other experience with a sprite sheet was in C# for a 2012 college project (which you can still find on GitHub), and in the XNA game engine, you can elect to display a portion of the image, say the 100×100 Facebook side. With CSS, the sprite sheet works slightly differently:

  1. You increase or decrease the size of the image, such that the foo x bar portion of the sprite sheet takes up exactly the size of the icon. This necessitates a fixed icon size.
  2. You then rotate through the sprites by moving the image. Instead of a separate process to select a portion of the image, you show the entire image, but arrange matters so that only the portion you need is what displays.
  3. Did I mention the icon size is fixed? The icon size is fixed, unless you apply an inordinate amount of CSS media queries or JavaScript $(window).resize() rules.

This works, don’t mistake me, but it smacks me as being hacky. The process feels backwards versus how this has worked for me in the past. I dorked around with the process a little bit tonight, and came up with a simple Scss mixin that hopefully reduces the amount of work and code needed to generate social media links. You pass it three parameters:

  1. Element for the links. This can be anything: a class (.foo), an ID (#bar) or an element (fizz).
  2. Icon size.
  3. Path to the SVG spritesheet.
@mixin generate-social-links($element, $size, $sprites, $service: null) {
    /*
     * Generate social Links
     * ---------------------
     * I wanted to reduce the work (and load time) of ubiqui-cancerous social 
     * icons. So:
     * 
     * 1. This uses a SVG spritesheet and is tuned to interact with it.
     * 1a. If you ever alter the spritesheet then you will also need to alter
     *     the given background-posiiton rules in the array.
     * 2. This will generate square icons of arbitrary size. These aren't 
     *    responsive, because that requires a great deal of of CSS or JS. It
     *    just isn't possible to use truly dynamic sizes with a stylesheet in
     *    CSS without using JS to resize everything.
     * 3. Social media icons are /usually/ small and fixed in size, so #3 isn't
     *    a big problem for me. 
     * 4. Pick a size of at least 35 pixels and then externally decide what 
     *    content should display at different sizes.
     */

    $columns: 6;
    $rows: 3;

    $social-styles: (
        beard: (#343537, 0, 0),
        discuss: (#b9dfbc, 20%, 0),
        email: (#f5756c, 40%, 0),
        facebook: (#3B5998, 60%, 0),
        flickr: (#ff0084, 80%, 0),
        github: (#666666, 100%, 0),
        google: (#dd4b39, 0, 50%),
        instagram: (#3f729b, 20%, 50%),
        linkedin: (#0976b4, 40%, 50%),
        pinterest: (#cc2127, 60%, 50%),
        print: (#007aaf, 80%, 50%),
        reddit: (#ff5700, 100%, 50%),
        rss: (#ff6600, 0, 100%),
        search: (#000, 20%, 100%),
        share: (#000, 40%, 100%),
        tumblr: (#35465c, 60%, 100%),
        twitter: (#55acee, 80%, 100%),
        youtube: (#b31217, 100%, 100%) 
    );

    /* Can be a class, ID, element-whatever. #foo, .a or baz, or a[href^=fizz]
     * are all perfectly acceptable. */
    #{$element} {
        background-image: url($sprites);
        background-size: #{$size * $columns} #{$size * $rows};
        background-repeat: no-repeat;
        display: block;
        height: 0;
        padding-top: $size;
        width: $size;
    }

    @if ($service) {
        // If you supply a service, just output link for that.
        #{$element}.#{$service} {
            background-color: nth(map-get($social-styles, $service), 1);
            background-position: nth(map-get($social-styles, $service), 2) nth(map-get($social-styles, $service), 3);
        }
    } @else {
        // Else iterate map to produce social links.
        @each $service, $nth in $social-styles {
            #{$element}.#{$service} {
                background-color: nth($nth, 1);
                background-position: nth($nth, 2) nth($nth, 3);
            }
        }
    }
}

I use it in the below manner for the Ouro landing page:

$image-folder: '../images';
$social-sprites: $image-folder + '/social/social-sprites.svg';

...

ul#nav-social, ul.team-social {
    @include generate-social-links(a, 35px, $social-sprites);
}

If you add or subtract icons, you must update the array of relative positions. There is no way for Sass to access an image, determine its size and change the array to reflect alterations. Sizes work like this:

  1. Give the mixin a size, say 50px.
  2. The height of the box is equal to the width, using a really cool trick that has been around since 2009. So, 50×50.
  3. The SVG spritesheet uses an 6×3 layout. Six columns, three rows.
  4. The size of the spritesheet, as a background object is set to $size * 6 by $size * 3, or in this case 300×150.
  5. The array contains the service colour and relative position as a percentage, so the size you input can be anything at all.

This is all awesome, but it doesn’t allow for dynamic resizing. I need to know the size of the icon for 100% dynamic sizing. As I said above, it requires a craplot of CSS for different window sizes, or you can use a spot of JavaScript:

// Give social icons a unique identifier for this to work.
var socialFoobar = {
    type: '.whatever',
    columns: 6,
    row: 3
}

var resizeSocialSprites = function() {
    /* This only works and should be needed if you gave the icon a dynamic 
     * percentage size, instead of a fixed pixel size. In that case it will
     * dynamically resize the icon's background-size */
    $(socialFoobar.type).each(function() {
        var height = $(this).height();
        var padding = parseInt($(this).css('padding-top'));
        var width = $(this).width();

        // If you use padding-top to set height, height will be 0.
        height = (padding > height) ? padding : height;

        $(this).css({
            // To stop height being added to width
            'background-size' : width * socialFoobar.columns + 'px ' + height * socialFoobar.rows + 'px'
        });
    });
};


$(window).on('resize', resizeSocialSprites);

So there you go: dynamic CSS social media sprite sheets through Scss and with a helping hand from jQuery. You can find all of the code in this GitHub gist too.