On Icon Fonts

I really respect Chris Coyier, he’s the very reason I am in this industry. His recent post comparing icon fonts and SVG’s made me think about how I approach them, which in-turn led me to think of benefits of continuing to use then in the way I already do.

This is not an attack on Chris’ article, more an addition. Another side to the coin. Before you continue though, I urge you to read Chris’ article, as most of what comes below won’t make sense. I didn’t want to copy lots of the article.

His article concludes that, if you can, SVG’s are better supported in modern browsers (IE 9+ & Android 3+) and I’m sure his research is solid. I want to explain why I’m sticking with icon fonts for every situation I need them.

My Responses

Icons are Vector

Browsers consider it text, so the icons are anti-aliased as such. Can lead to icons not being as sharp as you might expect.

True, but text is also vector (sometimes). Take a look at the example below. What looks sharper to you? I have compared this on my external display as well as a Retina MacBook Pro screen. On non-Retina, the left is sharper, where as on Retina, both are as sharp as each-other. The left is text, the HTML entity for the Apple logo, to be specific – . (May not work on non-Apple devices)

See the Pen iJrdB by Paul Adam Davis (@PaulAdamDavis) on CodePen.

CSS Control

Cannot argue here, SVG’s are easier to control specific parts.

Positioning

Also agree here, but with one exception. I usually always position font icons which gives you finite control, such as top: 1px;, so long as the position is relative, absolute or fixed, if you’re mad.

Weird Failures

Inline SVG is right in the document. If the browser supports it, it displays it.

Why would anyone actually put SVG’s right in the document? They’re huge. Using SVG icons should be synonymous with sprites. But using sprites leaves you open to a lot of the same loading issues you get with icon fonts. Web is hard.

Semantics & Accessability

Also true, but an icon typically has no real value. It should always be accompanied by some sort of descriptive text, whether beside it or hidden inside the element containing the icon.

Aside: In Ghost, we add speak: none; to icons (see the spec), and they’re almost always coupled with text. No icon? No real problem. It’s rare that an icon isnt next to some text of some sort.

Ease of Use

For the most part, Chris’ points are true. Using a pre-made icon font is almost always far to heavy for anyones use.

In Ghost, we create our own icons and use IcoMoon to create our own small font. The ttf font for ghost.org is 13kb (which has more icons than the blogging platform itself), the Font Awesome ttf is 81kb. It all makes a difference.

Conclusion

There are 3 main ways of adding (resolution-independent) icons.
Here’s a list of the pros & cons.

Inline SVGs

  • Very heavy initial HTML payload
  • Easier to style specific parts
  • Tougher to swap one icon for another
  • Only supported well in modern browsers, but fails well

SVG Sprites

  • No where near as easy to use as image sprites
  • Easier to use than inline SVGs
  • Only supported well in modern browsers, but fails well
  • Tough to style (akin to styling image sprites)

Icon Fonts

  • Easy to add to pretty much any element
  • Relatively small payload
  • Painless to add/remove icons
  • Best support of all the options

I’ll be sticking to icon fonts, rather than inline or sprited SVGs.

Submitting Forms Outside Forms

There are rare occasions where you need to have a submit button outside the <form> element.

Let’s say a page contains a few forms. One with settings, and another which sends a different kind of request to a totally different action, but the design dictates the submit button for the settings is somewhere which makes it damn-near impossible for it to be inside the <form> without some heavy and unreliable CSS.

For occasions like this, I like to have a fake submit button elsewhere on the page, which when clicked, submits the real submit button, via JavaScript. I have used this in Kodery before, and it works a charm.

Granted, it does require JavaScript, but when used in a web application that requires JavaScript for some crucial functions to work, this is not really an issue. If it is an issue, using a <noscript> tag or adding extra styles using html.no-js (like in a proper implementation of Modernizr), you can easily show the hidden submit button.


Below, is a barebones example of the markup.

<!-- The settings form -->

<form action="/api/settings" method="post"><input name="someinput" type="text" />
<button id="the-form-button" class="hidden">Submit</button></form><!-- The pesky form in the middle of the page -->

<form action="/api/Delete" method="post"><button>Delete Things</button></form><!-- And somewhere else on the page... -->
<a href="#" data-pseudo-click-target="the-form-button">Save Settings</a>

And this is the JavaScript (jQuery in this case).

$("[data-pseudo-click-target]").on("click", function(e){
e.preventDefault();
var target = $(this).attr("data-pseudo-click-target");
$("#" + target).click();
});

It may not be the best aproach for this kind of problem, but it is simple, easy to understand and is very flexible.


Update: 17-04-2014 12:09pm

Scott Riley has an alternate, but similar technique, in this gist.

The method shown in the gist uses .submit() which can be more suitable. Worth thinking about that.

Sass @content

While digging through some code earlier today, I saw @content for the first time, but it arrived in Sass in 3.2.0. They say you should learn something new every day, well I certainly did!

What it does, it makes your code cleaner, by enabling you to write less code. Let’s use an icon font mixin as an example. Take the following mixing.

@mixin icon($character) {
    &:before {
        font-family: "Icons";
        content: '#{$character}';
        @content;
    }
}

To use it, you’d write something like. The padding-left: 1rem; (and anything else in the curly braces) is output in the mixin with thanks to @content. In this particular case, it’s output inside the :before pseudo-selector.

.element {
	@include icon(\e123) {
		padding-left: 1rem;
	};
}

The old way to achieve the same end result was the below. Admittedly, it’s only 1 line longer, but is cleaner and includes one less selector.

.element {
    @include icon(\e123);
    &:before {
        padding-left: 1rem;
    }
}

Benefits?

Well, Sass is meant to make your life easier. If we stick with the icon font mixin example, surely it makes sense to group together styles related to the icon its self. Another point of Sass is to aid maintainability, so being able to move around where the @content is output is a nice bonus. Here’s a list for people who like lists.

  • Aids maintainability
  • Code looks cleaner
  • You write less selectors

Good to know

  • Media queries work inside it…
  • … other mixins too

Isn’t Sass fucking awesome?

Adding a Photo Layout to Ghost

I’ve always loved photography. It’s rare that I take a really good photo though, but for when I do, I want to share it. I like Instagram and all that, but sometimes I want to share a photo that isn’t square and locked at a tiny resolution of 612px. So, this weekend, I decided to add a photo layout to this blog.

The idea is basically to let images grow outside the bounds of the main wrapper element, which centres everything else. It’s a common technique and layout.

Note: The styles below are directly lifted from this blog, so you may need to change some things to make them work for your blog.

The Theory

Ghost has always has tags, so I use those. For a photo post, I add the tag of Photos or Photo, depending on how many images there are.

The HTML

Inside the post.hbs file, make sure the wrapper still has the tags helper.

<article class="">

That results in this.

<article class="post tag-photos">

I should add here that images are wrapped in

 

tags, which means slightly more verbose CSS.

The CSS

(I’m using Scss, compiled with CodeKit)

// My generic image styles used globally throughout the site
.post-content img {
    max-width: 100%;
    display: block;
    margin-left: auto;
    margin-right: auto;
}

// The meat of this post
article.tag-photos,
article.tag-photo {
    .post-content {
        img {
            // The `calc` means images touch the
            // edge of the browser on small screens
            @media (max-width: 700px) {
                max-width: calc(100% + 40px);
                margin-left: -20px;
            }
            @media (min-width: 800px) {
                max-width: 760px;
                margin-left: -30px;
            }
            @media (min-width: 900px) {
                max-width: 900px;
                margin-left: -100px;
            }
            @media (min-width: 1200px) {
                max-width: 1100px;
                margin-left: -200px;
            }
            @media (min-width: 1400px) {
                max-width: 1300px;
                margin-left: -300px;
            }
        }
    }
}

So what’s going on here? Let’s use the 1400px media wuery as an example.

When the screen is at least 1400px wide, make the image 1300px wide, then pull it left 300px.

Because the wrapper of this site is 700px, the image is an extra 600px wider than the wrapper, so to make it central, we pull it left. For smaller screens, the image is less wide, so we pull it left a smaller amount.

Here’s a visual explanation, and an example!

dsc_0152