Smarter RGBa fallbacks with Sass

I've been working on a client site that's been making great use of colourful transparent colours for defining the main categories of their resources. The development spec also required support for Internet Explorer 8 and as we know, RGBa isn't supported so I needed a fallback.

Currently

Looking at current suggestions or 'best practices' for using RGBa with a fallback for older browsers gives us the idea to use the block colour used for the RGBa as a back up, like this -

.element {
    color: #FF0000; 
    color: rgba(255, 0, 0, 0.5);
}

I think that, although it's an acceptable answer, it's pretty crappy. You site visitors would get something that looks good on their older browser still. Wouldn't it be better to offer them a fallback colour that's closer to the transparent colour?

Colouring Function

So I took to codepen to thrash out a little bit of Sass which gives you the transparent colour with a (close as possible without hand coding) fallback.

I say it's close as possible because the transparent colour will react differently to a lighter or darker background but using a closer fallback, I think, is better than just the non-transparent colour.

After some playing with some code I worked out roughly what numbers I needed for both and I came to this function -

@function trans($color, $percentage) {
    @if $percentage == .1 {
        @return lighten($color, 45%);
    }
    @if $percentage == .2 {
        @return lighten($color, 40%);
    }
    @if $percentage == .3 {
        @return lighten($color, 35%);
    }
    @if $percentage == .4 {
        @return lighten($color, 30%);
    }
    @if $percentage == .5 {
        @return lighten($color, 25%);
    }
    @if $percentage == .6 {
        @return lighten($color, 20%);
    }
    @if $percentage == .7 {
        @return lighten($color, 15%);
    }
    @if $percentage == .8 {
        @return lighten($color, 10%);
    }
    @if $percentage == .9 {
        @return lighten($color, 5%);
    }
}

This recreates a fallback colour estimated from the percentage of colour you're wanting for your transparent image where $color is the hexadecimal colour and $percentage is the a of RGBa.

Mixin it up

To get this to work I needed a little mixin to use the function when I'm needing a transparent background color or text color. So I made this for it -

@mixin tran($type, $color, $percentage) {
    @if $type == color {
        color: trans($color, $percentage);
        color: rgba($color, $percentage);
    }
    @if $type == bg {
        background-color: trans($color, $percentage);
        background-color: rgba($color, $percentage);
    }
}

Going through this we would need to define a $type, be it a background-color(bg) or just a color(color). The hexadecimal colour($color) and the level of tranparency($percentage). We could then include it in our Sass(SCSS) code like this -

header {
    @include tran(bg, #00ff00, .8);
}

Which would gives us this resulting CSS -

header {
    background-color: #33ff33;
    background-color: rgba(0, 255, 0, 0.8);
}

Where the fallback colour is a lot closer to the RGBa than #00FF00 would be.

Close but no cigar

This bit of Sass(SCSS) gives us a 'close as possible' fallback. As the colour of a transparent element will change depending on the dark or light colours behind it. It's not perfect but it gives a closer fallback for your designs.

This is available now on codepen to grab and also now included in my Sass library Sassifaction

UPDATE - The great internet

So some hours have passed and @japborst has just submitted a lovely pull request to update the code and remove all of the @if statements. The code to get it to work for the function is now - 


@function trans($color, $percentage, $shade) {
 @return lighten($color, (1-$percentage)*5%);
}