Showing posts with label css. Show all posts
Showing posts with label css. Show all posts

Wednesday, August 8, 2018

Minor Comic Style Improvements

I've made a few minor adjustments to the comic's style coinciding with the restart. You might not notice unless you have a keen eye for detail.

Font Upgrades


First, I've set a specific font for the free-text in comic frames. The speech bubbles have always used Sniglet, but any text that just floated there was actually set to Verdana with a fallback to sans serif. Sure, it looked fine for Windows users and didn't look too bad when I viewed them on Linux, but sometimes I'd be on a weird browser and get a weird font that looked...weird. I don't know why I never fixed this in the first three years of the comic, but when I set my mind on it I had a lot of trouble picking a free font that I liked. I ended up going with Ubuntu. Now the text should look consistent for all browsers on all operating systems.

Here's a sample of a comic in the original font:

And here's that same comic using the new font:

The difference is subtle, but I think it's important. I'm much happier with the new font.

In addition that font fix, I've added another font option for comics. Anything that's supposed to look hand-written will now use the Architect's Daughter font. It's clean and easy to read but also warm.

Here's an old comic with writing on the whiteboard:

And here's that same comic, updated for the new font:

Mobile Theme Color


Mobile users may also notice another minor change that I've made. I set a "theme color" so the address bar will be green. Oddly enough, this is done via meta tags instead of CSS like I'd expected.

<meta name="theme-color" content="#006600">

Here's what it looks like for me, in Chrome for Android:



More to Come

That's all for now, but there are more updates coming along with the new comics. Here's this week's:

Amphibian.com comic for 8 August 2018





Monday, May 16, 2016

CSS3 Smoke Animation Effect

The comic today uses quite a bit of CSS3 animation. This is a rather new thing for me - I've been using mostly JavaScript-powered animations on Amphibian.com since it started. But after I did the rain animation using CSS back in March (see the comic here), I've been warming up to the idea of more CSS and less JavaScript to move things around.

For this task, I wanted to make some animated smoke come out of the frogs' rocket ship before the launch. My style is mostly just simple geometric shapes arranged to look like things, so using circular DIV elements to look like puffs of smoke was fine with me. I found a great starting point by Andrea Verlicchi on CodePen, and then modified it for my comic.

Here's the basic idea - puffs of smoke emanate from a given source element. They move downward and off to the side while fading away.

The puffs of smoke will be represented by rounded SPAN elements, with this CSS applied to them:

span.smokepuff {
    display: block;
    position: absolute;
    bottom: -35px;
    left: 50%;
    margin-left: -20px;
    height: 0px;
    width: 0px;
    border: 35px solid #4b4b4b;
    border-radius: 35px;
    left: -14px;
    opacity: 0;
    transform: scale(0.2);
}

The above styling just makes them round, grey, and positioned absolutely in their container. I also have two animation keyframes defined, one for the down-and-left movement and one for the down-and-right movement:

@keyframes smokeL {
    0% {
        transform: scale(0.2) translate(0, 0);
    }
    10% {
        opacity: 1;
        transform: scale(0.2) translate(0, 5px);
    }
    100% {
        opacity: 0;
        transform: scale(1) translate(-50px, 80px);
    }
}

@keyframes smokeR {
    0% {
        transform: scale(0.2) translate(0, 0);
    }
    10% {
        opacity: 1;
        transform: scale(0.2) translate(0, 5px);
    }
    100% {
        opacity: 0;
        transform: scale(1) translate(50px, 80px);
    }
}

The above keyframe definitions define an animation that will move the smoke puffs lower by 80 pixels and 50 pixels to either side while at the same time scaling them up and fading them out. It defines 3 steps: 0% (the start), 10% (moved a little down), and 100% (moved completely down and over). There's one for the left, smokeL, and one for the right, smokeR.

Note: if you care about being compatible with slightly older browsers, you would want copies of these with @-moz-keyframes and @-webkit-keyframes as the names as well as adding -moz-transform and -webkit-transform to them all! I left that out here to keep the example simpler!

I said this was pure CSS3 animation, but there's still a little JavaScript involved. It doesn't really do the animating, but I use some code to generate the puffs in the first place. Something like this:

function createSmoke(time, num) {

    var timeGap = (time / num); 

    for( var i = 0; i < num; i++) {

        var delay = (timeGap * i) + 's';

        var aniName = "smokeL";
        if (((i+1) % 2) == 0) {
            aniName = "smokeR";
        }

        var aniStyle = "animation: " + aniName + " " + duration + " " + delay + " infinite";
        $('#smoker').append('<span class="smokepuff" style="' + aniStyle + '"></span>');

    }

}

When this function is called, you give it the length of the animation and the number of puffs of smoke you want. It figures out how much of a delay there should be between each puff's animation starting based on those two values. For example, if you want the animation to run 5 seconds and have 10 puffs of smoke, the first puff would have no delay, the second would have a delay of ( 5 / 10 ) * 1, the third a delay of (5 / 10 ) * 2, and so on. In this example, that just means add a half-second delay for each puff you generate. Also, each time through the loop, it alternates between the smokeL and smokeR animations so that every other puff moves in the opposite direction. One final piece of the total animation style is to set the repeat-count to infinite, so the puffs keep on coming! The function generates new SPAN tags with these animation styles applied and appends them to the parent element, which here is named smoker. It's just a DIV somewhere on the page - all the puffs of smoke will appear to come out of it.

The finished animation. Don't miss it!

I think the effect turned out great. Even though I used a little JavaScript to create the elements, doing all the animation with JavaScript would have been much, much more complicated. I may consider replacing all the old JavaScript-powered animation on Amphibian.com with CSS animation, and fix up my animation editor to go with it!

Now don't miss the smoke effect in today's comic! If you're reading this on the publication day (16 May 2016) the countdown to launch will be live! That means the last frame of the comic will change and do different things right up to the launch time! Keep watching it!

Amphibian.com comic for 16 May 2016

Friday, March 11, 2016

A Rain Effect Using Only CSS

Today's comic contains something that I've never used before in a comic - CSS3 Animation. The rain effect in the first 3 frames is done purely with CSS! Here's how it works.

All the raindrops in each frame are just DIVs with a color gradient background.

<div class="drop></div>

The CSS style for a drop contains a special property, animation. The browser-specific versions, -webkit-animation and -moz-animation, are also specified to catch older browsers.

.drop {
    -webkit-animation: fall .68s linear infinite;
    -moz-animation: fall .68s linear infinite;
    animation: fall .68s linear infinite;
}

The format of the animation property's value is: <name> <duration> <timing function> <iterations>.

The name of the animation is whatever you want. Mine is called "fall" because that's what raindrops do. I specified a duration of 0.68 seconds, because I played around with it and just liked that duration the best. The timing function here is linear. That means there is no easing of any kind; the drops always move at a constant speed. Finally, I specified "infinite" for the number of iterations. The reasons for these values should make sense shortly...

I gave my animation a name, but I also need to specify what an animation with that name actually does. To do that, you use another CSS directive called @keyframes. (you can also use @-webkey-keyframes and @-moz-keyframes for older browser support)

@-webkit-keyframes fall {
    to {margin-top:700px;}
}

@-moz-keyframes fall {
    to {margin-top:700px;}
}

@keyframes fall {
    to {margin-top:700px;}
}

Here I am specifying that an animation named fall should alter the margin-top property until it reaches a value of 700px. Once that value is reached, one iteration of the animation is considered to be finished. Since I specified infinite iterations above, it means that every time the animation ends it will just reset to the original value and run again. The time it will take to change the margin-top value from whatever it starts at to 700px will be equal to the duration specified earlier.

All I had to do was give the raindrops a random position when I created them, and by animating an increase in their top margin they appear to fall past the bottom of the frame before being reset.

The end result is the beautiful rain effect you can see by clicking the link below and reading today's comic! CSS3 animations can be an easy alternative to JavaScript based animations. They're actually very well-supported by most browsers, even IE 10.

Amphibian.com comic for 11 March 2016

Friday, September 25, 2015

Faux Bold is Better Than No Bold

Today I'm going to forego another in-depth discussion of a new ES6 language feature that recently became available in Node 4. Instead, I'd like to make a brief mention of what I learned this last week concerning "faux" font styles and PhantomJS.

First of all, what are faux font styles? As I recently learned, when you use a web font and not all the special styles are available (such as bold and italic), the browser will just alter the normal version of the font to create the faux styles. As a side note, I also learned that faux has only been used in English by itself to mean "fake" since the 1980's. I am older than this usage.

So when a font has its own bold and italic styles available, you should probably use them. Typically, this is accomplished by specifying multiple @font-face directives in your CSS. Each should define font-weight and font-style appropriately.

@font-face {
    font-family: 'Whatnot';
    src: url('/css/Whatnot-Regular.ttf');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'Whatnot';
    src: url('/css/Whatnot-Bold.ttf');
    font-weight: bold;
    font-style: normal;
}

@font-face {
    font-family: 'Whatnot';
    src: url('/css/Whatnot-Italic.ttf');
    font-weight: normal;
    font-style: italic;
}

Like the above example, if you have multiple versions of the font you should use them. They'll probably look better than the faux versions made by the browser.

I use Sniglet as my standard font for the comics and it doesn't have an italic version. I have no choice but to settle for the faux version. It's not the end of the world, but I noticed a problem. When I made a comic that actually relied on bold italic text, the text was showing up as neither bold nor italic in the .png image generated by PhantomJS. Why?

After a bit of investigation, it would appear that PhantomJS can't make faux font styles out of SVG fonts. Any attempt to show bold or italic Sniglet was being ignored for as long as I've been making these comics. The solution? Switch to the True Type version of the font. It doesn't look that great when PhantomJS renders it but it's better than nothing.

Amphibian.com comic for 25 September 2015

Monday, September 14, 2015

Not a Chance

Luck has nothing to do with it.
Did you ever sit down to do something that you thought would be easy, only to give up in frustration many hours later? That's the story of today's Amphibian.com comic.

Well, maybe not the whole story. It started because I wanted to make a comic that included three things: scratch-off lottery tickets, a reference to The Lottery by Shirley Jackson, and a statement about the odds of winning the lottery.

One of my uncles gives a big stack of scratch-off lottery tickets to one lucky family member every year for Christmas. Everyone loves them for some reason. I've often wondered about the cost-to-wins ratio on those things, and how much time it would take to play a whole bunch of them. I thought I would make a comic where several of the frames were hidden beneath a silvery covering that could be "scratched" off with the mouse cursor on desktop browsers or your finger on mobile browsers.

The desktop, mouse-based interaction was fairly easy. There were just a few quirks that had to be addressed. Since the user would be holding down the mouse button and dragging a "coin" cursor all over the cell, there were the unfortunate side-effects of having the speech bubble text selected and the frog images getting drug around with that "ghost" effect.

To prevent text on a web page from being selected by the mouse cursor, there is some CSS that can be used. Here it is (with all the possible browser-specific versions):

.noselect {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

I simply applied this .noselect class to the text in the scratch-off frames. To prevent the image drag ghosting, the solution is to set a handler for the dragstart event on all the images which simply returns false. No drags allowed. I use jQuery in my comic to do these tasks, as is reflected by the following code snippets:

$('.myclass').addClass("noselect");
$('.myclass img').on("dragstart", function() { return false; });

With those two issues out of the way it worked great on the desktop. Oh, but those mobile browsers... I had thought that I could make the page perform pretty much the same way on mobile by using touch events in addition to mouse events. I was wrong. So very wrong.

On the desktop it works by detecting the mouseenter event. When the mouse cursor enters on the cover elements (a bunch of rounded divs), the element is removed if the mouse button is down. In a mobile browser, there is of course no mouse cursor so I attempted to use a touchmove event instead. If the user is touching the screen and moves over one of the cover elements, it should vanish. Except that doesn't work.

It turns out that the target of a touchmove event is always the same element - the one where the touch started. Not that helpful, but I thought I could deal with it. Instead of capturing a finger moving across the cover divs, I could track the page X/Y of the touches on the comic cell div and use the little-known document.elementFromPoint(x, y) function to figure out which cover elements to remove.

var elem = document.elementFromPoint(x - window.scrollX, y - window.scrollY);
$(elem).remove();

Well, that maybe sorta worked. To get the right element you have to adjust for the page scroll, but the performance was terrible on my phone. I could have probably worked on it some more, but it was time to cut my losses. I'd spent too much time on this problem already. I made a mobile-specific, not-quite-as-cool, auto-scratch-off effect and called it a day.

I hate it when this happens, but it's worse to not ship than to ship with a sub-optimal product. At least in my opinion. That's why there are comics 3 times per week, even if some are terrible.

Amphibian.com comic for 14 September 2015

Wednesday, August 5, 2015

CSS Grayscale Filter (not Greyscale)

Today's comic pokes a little fun at Internet Explorer. It's certainly not the first time I've done that. The comic talks about one of the most ubiquitous features of modern browsers, tabs. And while there was a time when no browsers had them, I chose IE for the comic because it got them later than anyone else. Microsoft's victory in the Great Browser Wars was a loss for the world - as all web innovation stagnated for years in a single-browser ecosystem.

The ironic thing is that the comic uses a feature that is not supported by even the latest version of Internet Explorer. No, wait. Ironic isn't the right term. What word am I looking for? Oh yeah, expected. The expected thing is that the comic uses a feature not supported by IE. Because it never seems to support anything, even today!

Alright, enough of the IE-bashing. The feature I'm talking about is CSS Filters. Microsoft used to support a propriety version of most of them, so at least developers had an option to make pages look similar in all browsers, but they removed that support in IE9. Even 11 doesn't support Filters yet, although it looks like it might soon. But it should, because filters are great.

The same page in Chrome 44 (left) and Internet Explorer 11 (right)
The filter I used today was grayscale. Why not greyscale? I don't know, what's up with the whole gray/grey thing? Maybe I'll talk about that some other time...

I wanted to show a comic cell that was the imagination of something in the past. Even though the date was only 2003, everyone knows that the past is always in black-and-white. So I used the grayscale filter to get rid of 80% of the color.

<div id="cell-2" style="-webkit-filter: grayscale(80%); filter: grayscale(80%);">

    <!-- comic cell contents here -->

</div>

It's really simple to use. Just specify a percentage of how much grayscaling you want. 100% will mean absolutely no colors. I left 20% of the color there and I liked how it looked. It's not 1950's black-and-white, but it still makes you think of the past. Note how I did it on the container DIV and all elements inside of it were in grayscale. It works on all elements, not just images.

I have to use the -webkit-filter and filter both because only Firefox currently supports the standard version. Still, better than IE where I get nothing. In the past I've avoided including things like this in the comics. If I couldn't make it happen in the modern version of all the major browsers I wouldn't do it. But I felt that in this case, the missing feature doesn't detract much or ruin the joke - so I went ahead with it.

Some other filters that I've wanted to use are invert and blur, but they were going to be more integral to the joke and without IE support I didn't do it. IE is limiting my creativity!

So enjoy today's comic - preferably not in Internet Explorer.

Amphibian.com comic for 5 August 2015

Wednesday, June 24, 2015

Responsive SVG

I mentioned the other day that I was working on an update for caseyleonard.com that included even more full-screen frog images. Much like the current site, I want to use SVG images and have the frogs scale right along with the browser window, for a smooth responsive effect.

And as usual, Microsoft Internet Explorer has to ruin the party.

Instead of using <img> tags for the frogs this time, I am going to embed SVG markup directly in the HTML of the page. This has been possible for quite a while (IE support began with version 9) but is not often seen on "normal" web pages. Any page with my name on it will be far from normal.

You can try this yourself if you have some SVG lying around. It's best to use minified SVG (see last Wednesday's post) so your pages don't get too terribly large. Here is an example with the actual SVG stuff blanked out to save space:

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Responsive SVG</title>
</head>

<body>

  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 276 281">
    ...
  </svg>

</body>

</html>

By including a viewBox attribute to set the aspect ratio of the image and not including width or height attributes, good browsers like Chrome and Firefox scale the image to the maximum width of the container. Bad browsers like Internet Explorer assume a fixed height of 150 pixels and scale the width to create an image with the appropriate aspect ratio. Huh?

Properly scaled frog, in Chrome

Improperly scaled frog, in Internet Explorer

It turns out this is a known issue with IE, and it easily correctable with some CSS. First, wrap the SVG element in a <div> of class container. Then add the following CSS to the page:

.container {
    width: 100%;
    height: 0;
    padding-top: 102%;
    position: relative;
}

svg {
    position: absolute;
    top: 0;
    left: 0;
}

The value of container width is 100% because I want the frog to be as big as the window. You can use other values if you want your image to be smaller. The value for padding-top is calculated based on a formula and will be different for every image. To get the percent for padding top, do

( ( svg height) / (svg width) ) x (container width)

So in my example, the height of the frog image with my desired aspect ratio (from the viewBox) is 281 and the width is 276. I divide height by width and then multiply by 100 to get a value of 102. I use that for the padding-top percentage. Another look at the page in IE shows the correct result, and the page looks unchanged in Chrome.

Correct this time, Internet Explorer

And that looks much better! It's still a shame that IE makes us do all this extra work. And speaking of extra work, in today's comic the frogs take server hardening a little too far.

Amphibian.com comic for 24 June 2014

Friday, June 19, 2015

Numbers Aren't Always Numbers on iOS

A weird bug was brought to my attention yesterday concerning the Pivot comic from back at the end of May. If you read them regularly, you will remember that it was the one that had some frogs and a speech balloon spinning around (like a record, baby). The frog spinning was just an animation but the speech balloon rotation was an effect produced by changing the CSS transformation scaleX between 1 and -1. It creates the illusion that the balloon is rotating on a horizontal plane.

Based on a timer, I simply add or subtract a fraction of the scale value every few milliseconds. It worked fine on most platforms, but on iOS Safari there was an anomaly for small values very very very close to zero. A number like -0.000000000000005793976409762536, for example.

Because of the way numbers work in JavaScript, converting a number like that to a string value that can be used in a CSS property ends up looking like "-5.793976409762536e-16". And that's what Safari doesn't like. Apple even investigated it and everything. The official response was that it doesn't parse as a valid transform value. To fix it, I just call .toFixed(5) on the number before I put it in the CSS scaleX property. Five decimal places is plenty of precision, and it ensures that I never get the e thing in there.

But technically, I think it should have worked the way it was. According to the W3C specification, the value of scaleX (and other transforms as well) should be a real number - which can be expressed with the exponent notation. Okay, I realize the CSS Transformations is just a draft...so I guess I'll go easy on Apple this time (even though 75% of the editors are Apple employees!).

But interesting tie-in...today's comic also focuses on speech balloons. Well, technically on a sub-category of speech balloons - thought balloons. Have you ever thought about the history of speech balloons? Neither had I, before this evening. However, it turns out that balloons or bubbles showing the words spoken in a painting or drawing can be traced back hundreds of years.

Before the 18th century, speech was often indicated by strips or bands coming out of people's mouths, such as the one depicted here:


This was difficult to read, and rather limiting. By 1896, what might be considered modern speech balloons had started to be used with The Yellow Kid in the comic Hogan's Alley. The Yellow Kid is considered to be the first American comic strip character because of his recurrent appearances in the strip. Within a few years, other comic authors adopted the style and here we are today.

Hopefully, someday people will look back at the innovative things I've done with web comics and say how I introduced such pivotal devices to visual story-telling. It could happen. Help me out by reading and sharing today's comic:

Amphibian.com comic for 19 June 2015

Monday, April 20, 2015

Using Your Own Custom Web Fonts

Olde Geoff coude telle a goode tale.
It is the month of April, and you know what that means. Yes! The Canterbury Tales! Geoffrey Chaucer's most famous work of Middle English literature was set in April near the end of the 14th century. I loved reading the Tales as part of my high school literature requirements and have never forgotten them.

As a tribute to Chaucer some 600+ years later, Amphibian.com will be written in the style of the Tales for the next week and a half. It starts out with an unnamed narrator meeting up with a group of frogs in an airport. They're all travelling to the Moscone Center in San Francisco for a conference and agree to tell each other stories to pass the time. In the Canterbury Tales, it was a group of pilgrims travelling to Canterbury. If you've never read Chaucer's original, you can find it here: The Canterbury Tales.

I say all that as an introduction to the real topic of the today's post - using your own custom fonts on web pages via CSS.

I had to do this for the comics to get a font that looked Middle English. The font I'm using is, oddly enough, named Canterbury. You may be familiar with using Google Fonts to add a custom font to web pages, but they don't actually offer one in the Middle English style. That's why I had to do it on my own. It's not hard to do, and is the same method used by Google Fonts and font-based icon utilities such as Font Awesome.

The first thing you need is a font. There are many places on the web to find fonts, but make sure you are adhering to the license agreement. Some are public domain, others you have to pay for, and some are provided under one of the Creative Commons licenses. Here are some popular font sources:

Besides just having a font, you need to have that font 4 different ways. Each browser has its own set of supported formats, so if you want complete functionality across all browsers you'll need to have the font in EOT, SVG, TTF, and WOFF formats. You can usually find fonts in TTF or OTF formats. What if you don't have the rest? There are some free utilities on the web that can convert to the other formats for you. I used Font2Web but Font Squirrel has a similar service that I used once in the past.

Once you have all those font files, you need to define the font in your CSS. You do this with the @font-face declaration. In it, you give the font a family name and specify the URLs for the various file formats. Here is the CSS for the Canterbury font:

@font-face {
    font-family: 'Canterbury';
    src: url('../fonts/Canterbury.eot');
    src: url('../fonts/Canterbury.woff') format('woff'), url('../fonts/Canterbury.ttf') format('truetype'), url('../fonts/Canterbury.svg') format('svg');
    font-weight: normal;
    font-style: normal;
}

Note that if you use relative paths in the URLs, they are relative to the location of your CSS file. I keep my fonts in a directory named fonts which is sibling to my css directory.

Once you have your font defined, you can use it in styles by referencing the font-family name you gave it above.

.olde-text {
    font-family: 'Canterbury';
    text-align: left;
    font-size: 1.3em;
}

As you can see, it's not that hard to use your own custom fonts in web pages. It was easy to make my text use a Middle English font. What's not easy is reading Middle English and understanding what it means. But give it a try anyway in today's comic.

Amphibian.com comic for 20 April 2015

Monday, April 13, 2015

Goodbye, GitHub Game Off 2015

And so today the GitHub Game Off 2015 has ended. The last four weeks have been busy, but I'm happy with my entry this year. Even though I didn't get to write a game completely from scratch like I did back in 2013, learning the Crafty framework was worth it.

Learning to use a new framework is good in itself, but what I've really liked about Crafty is that I've found such interesting things while looking at its source code. I wrote last week about how it is able to make read-only fields on JavaScript objects, but here's another neat trick I found.

One feature that Crafty offers is the ability to draw the game entities with either Canvas or the DOM. You can even mix the two in your game, like I did in mine (it was done that way in Octocat Jump originally). All "2D" entities have a .flip() method which, you guessed it, flips the entity's image backwards. I thought I knew how this was done for Canvas entities, but it also works on DOM entities. I had to look in the code to see how the flip was performed.

When I saw it, I said to myself, "Of course! Why didn't I think of that?"

You can flip any element in the DOM using the CSS3 2D transform scale methods. Just set the scale to a negative number.

<div id="flipMe" style="transform: scaleX(-1);">
    this will be backwards
</div>

You can do it programmatically with jQuery just as easily.

$("#flipMe").css("transform", "scaleX(-1)");

I knew you could scale DOM objects this way but it never occurred to me that a scale of -1 on the X or Y axis would just flip the object!

Flipping a comic cell. The one on the right has had a transform of  scaleX(-1) applied.

Just another reason that I love looking in open source code, and you should too! Hopefully GitHub posts a list of all the Game Off 2015 entries soon, so we'll all be able to learn new techniques by looking at other people's code.

You know what else you should love looking at? My frog comics! Here's a link to today's...

Amphibian.com comic for 13 April 2015

Friday, February 20, 2015

It Keeps Blinking, But I'm Not Turning

You know what I miss about the Internet from the 90's?

Blinking text!

You know you miss it too! You don't have to live in denial any longer. Just accept it. It's okay.

Blink.

Blink.

Blink.

Even though Netscape Navigator is a distant memory, it's easy to relive your glory days of website design by making text blink using jQuery. It's really easy.

Just take whatever elements you want to blink and add the blink class to them, like I did with this paragraph tag:

<body>

  <p class="blink">This text should blink.</p>

</body>

Then in a script tag, just do this (updated):

$(function() {

    var vis = "hidden";
    function bringBackBlink() {
        $(".blink").css("visibility", vis);
        vis = ( vis === "hidden" ? "visible" : "hidden" );
    }

    setInterval(bringBackBlink, 500);

});

Updated: After the bringBackBlink (say that 5 times fast) function is defined, setInterval makes sure it gets called every 500 milliseconds. All the function does is find all elements on the page that have the blink class and toggles their display visibility value. If they are visible, they become hidden. If hidden, they become visible. It will happen twice every second. If you want to make them blink faster or slower just change the millisecond value.

As pointed out in the comments, I originally used jQuery's .toggle() function to alternatively hide and show the element. This will only work correctly in situations where the element to be blinked is using fixed or absolute positioning (that's why it works for me in frog comics). In "normal" situations, like my paragraph tag example above, all the other elements on the page will shift around. This is because jQuery's toggle function sets the value of the display property to none, which causes the hidden element to no longer take up space on the page. Using the visibility property instead keeps things where they belong.

Now look at this example of HTML. It has lots of other non-blinking elements on the page that won't shift around when things blink.

<body>

  <p>This text should not blink.</p>

  <p class="blink">This text should blink.</p>

  <p>This text should not move.</p>

  <p class="pink">
    <span class="blink">
      This text should blink and be pink.
    </span>
  </p>

  <p>This text should not move.</p>

</body>

<style>

.pink {
    background-color: #000000;
    color: #FF3399;
    padding: 5px;
}

</style>

Here is an animated GIF showing the results:


Just like neon windbreakers and cargo pants, blinking text on the web is coming back in style! (Disclaimer: I don't actually know if neon windbreakers and cargo pants are coming back in style)

And speaking of blinking...if you still have your Christmas lights up like the frogs do, it might be time to take them down.

Amphibian.com comic for 20 February 2015

Monday, February 16, 2015

Being Awesome

In today's comic, the frogs of today and of ancient times are using pictures instead of words to convey meaning. The problem is that sometimes the meaning is lost. My children know that the picture of a floppy disk means Save, but they have no idea what a floppy disk is.

Despite this problem, I do like to use small pictures on web pages to represent certain actions. If you'd like to do this as well, be sure to check out Font Awesome (if you haven't already). I used to create small images myself to use on web pages in <img /> tags for this purpose, but doing this with fonts and CSS makes even more sense. When the image is a scalable, vector-based character from a font, you can make it any size/color/rotation you need.

Using Font Awesome can seem like magic. You just put an empty tag in your HTML with a couple classes applied to it and it renders as a picture of something. The following example is the bomb!

<i class="fa fa-bomb"></i>

There is no actual magic involved, however. The CSS that accompanies the Font Awesome font makes use of the ::before pseudoelement to add a character of text to your markup. The character added depends on the class and maps to one of the images in the font.

Pseudoelements let you do all kinds of crazy things via CSS. Like ::before, there is also an ::after. They allow you to add text or images (or nothing) to the page, but the additions don't actually become part of the DOM. That last part makes them a little difficult to work with sometimes, but they are still useful. Here's a weird example:

a::after {
    content: " (don't click on this!)";
}

That will add a dire warning to every link on the page. I didn't say it was a useful example. I said weird.

If you'd like some useful examples, check out CSS-Tricks. But don't forget about Font Awesome if you just want to put some icons on your pages now. And also don't forget to read today's comic.

Amphibian.com comic for 16 February 2015

Monday, February 9, 2015

It's All a Blur

How many times have you wanted to blur all or part of a web page? If you're anything like me (which you're probably not because I'm a weirdo), it happens all the time.

I tried to do this the other day and learned that there aren't a lot of good options. There is hope, however, since Chrome supports CSS Filter Effects, which include blur. It's only supported by Webkit at the moment (since Chrome 18), but we know that features such as this tend to seep into other browsers over time.

Using the Webkit filter is easy. Just apply a style like this:

-webkit-filter: blur(8px);

And just like that, your page content gets blurry.

But I know, not everyone is using Chrome. Some poor misguided individuals are still using Internet Explorer. What can be done? The good news is that in many simple cases, a jQuery plugin can provide a polyfill for the missing blur feature.

I tried out Foggy, one such plugin. If used in Chrome, -webkit-filter is applied. Otherwise, it dynamically creates a bunch of copies of the element and makes each one slightly transparent and offset to simulate the blurring.

Here it is in action on my comic. All I had to do was include the jquery.foggy.js file and then

$("#cell-1").foggy();

To get this result:

Foggy applied to a comic cell in Chrome
Looks good, right? Yeah! But that was in Chrome, my browser of choice. Let's see what happens in Firefox...

Foggy applied to a comic cell in Firefox. Whoa!
Fail! Not only did it make this cell look weird, it actually screwed up the element locations in the previous cell too. Clearly, this isn't going to work for me.

Don't discount Foggy for your own projects just yet. When applied to "normal" text and images, like in their demo page, Foggy does produce correct results in Firefox and Internet Explorer. It might work for you, depending on what you are doing with it.

But one thing is clear, and that is the fact that the future is blurry. Don't forget to read today's comic, where we continue to see what happens when frogs don't think clearly. Plus, make sure you check out our current FREE STICKERS promotion. There's a link at the top of the comic page for details!

Amphibian.com comic for 9 February 2015

Monday, September 22, 2014

When Computed Styles aren't Computed

I noticed something unexpected the other day when working with jQuery to read CSS dimension properties. Maybe everyone else in the world is already aware of this but I'll talk about it anyway.

Typically, whenever you use jQuery to read the value of a height or width property of an element, the value is always returned in pixels. You can set the value in %, px, em, cm, whatever. But it always comes back to you in pixels. It will actually be a string with "px" at the end.

Except when it's not.

I was relying on this behavior. I would grab the value, remove the "px" from the end, and turn it into a Number. But sometimes I was getting "NaN" as my value. Upon closer inspection, it turned out that I was getting a value like "82%" instead of "435px" which was throwing everything off.

Technically, jQuery is giving me what is known as the computed value of the property. Sure, sometimes getting the value in pixels is not what you want, but as long as it's consistent you can deal with it. I was encountering the problem that sometimes it was in pixels and sometimes it was the value that I set it from, which happened to be percent.

It took me a while, but I finally figured out what was going on.

When the element's parent (not the element itself) has a display value of "none," the browser can't give me the computed dimensions because it has no way to compute them. Instead, you get whatever value the CSS says.

Check out this test page I put together to demonstrate the issue.

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>CSS Test</title>
</head>

<body>

  <div id="container" style="width: 400px;">
    <div id="test" style="width: 50%">test</div>
  </div>

</body>

<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>

$(function() {

    console.log($('#test').css('width'));

    $('#container').toggle();

    console.log($('#test').css('width'));

    $('#container').toggle();

    console.log($('#test').css('width'));

});

</script>

</html>

Here is the console output.


As you can see, the test div has a width specified as 50% but when the value of the "width" CSS property is printed out, it is "200px". This is exactly correct, since 200px is 50% of the 400px width specified on the parent container.

After I toggle the visibility of the parent container (the jQuery .toggle() function) and print the width of the test div again, I get a value of "50%". That's what the style attribute says.

Toggle the parent container visibility again (make it visible) and you see "200px" on the console again.

Once I learned this and restored my sanity, I was able to fix my problem easily by making my elements' parent visible before I tried to read the dimensions. Originally I was trying to read them, perform some calculations, and then make the parent visible. There were no real issues with switching the order around a little in my case, but your mileage may vary.

Amphibian.com comic for September 22, 2014

Monday, August 18, 2014

CSS Speech Bubbles

I'd like to take a moment to talk about my CSS speech bubbles. My comic uses CSS rules for making <p> tags render as speech bubbles for the frogs. If you view the page source, you'll see that there are no tables or images involved - just pure CSS.

There are many examples out there on the Internet about how to achieve this effect. I based mine on this one: Bubbler - CSS Speech Bubble Generator. Of all the examples I saw, I just like this one the best.

There was one minor issue I came across though. The frogs are in different places in each cell, but because the bubble stems are positioned using the CSS psuedo-elements ::before and ::after, the values that determine the stem location cannot be set via JavaScript.

I decided to solve this issue by removing the stem position from the .bubble::before and .bubble::after classes in the CSS, and creating another set of classes just for the stem positions.

I called these new classes bubble25, bubble50, and bubble75. You can probably guess that the number represents the percentage used for the left attribute in the stem position.

So now, if I want to create a speech bubble with the stem on the right side (75% of the bubble width) I create a tag like this:

<p class="bubble bubble75">here is some content for the bubble</p>

While I can't position the stems at every possible position this way, having the 3 different options has proven sufficient so far. This is a good example of a design trade-off. I could create a hundred different classes and never use 90% of them, or I could create just 3 and get a good-enough position 99% of the time.

Here's a snippet of my CSS that shows more clearly what I'm talking about.

.bubble {
 position: absolute;
 width: 44%;
 padding: 2%;
 text-align: center;
 background: #FFFFFF;
 border: #000000 solid 3px;
 font-family: 'Sniglet', sans-serif;
 line-height: initial;
 color: #000000;
 box-sizing: content-box;
 -moz-box-sizing: content-box;
 -webkit-box-sizing: content-box;
 -webkit-border-radius: 20px;
 -moz-border-radius: 20px;
 border-radius: 20px;
}

.bubble:after {
 content: '';
 position: absolute;
 border-style: solid;
 border-color: #FFFFFF transparent;
 display: none;
 width: 0;
 z-index: 1;
 box-sizing: initial;
 -moz-box-sizing: initial;
 -webkit-box-sizing: initial;
 border-width: 21px 7px 0;
 bottom: -21px;
 margin-left: -12px;
}

.bubble:before {
 content: '';
 position: absolute;
 border-style: solid;
 border-color: #000000 transparent;
 display: none;
 width: 0;
 z-index: 0;
 box-sizing: initial;
 -moz-box-sizing: initial;
 -webkit-box-sizing: initial;
 border-width: 25px 9px 0;
 bottom: -27px;
 margin-left: -14px;
}


.bubble25:after {
 left: 25%;
 display: block;
}

.bubble25:before {
 left: 25%;
 display: block;
}

.bubble50:after {
 display: block;
 left: 50%;
}

.bubble50:before {
 display: block;
 left: 50%;
}

.bubble75:after {
 display: block;
 left: 75%;
}

.bubble75:before {
 display: block;
 left: 75%;
}

Make sure you check out John Clifford's Bubbler to make your own bubble CSS. Speech bubbles can be a welcome addition to any web site.

Amphibian.com comic for August 18, 2014