Repeating Lateral Text Shadows

I’ve wanted to do this effect for some time now. It consists of one or more lines of text with variable indentation, and seemingly ever-repeating washed out copies of the text on both sides running off screen.

Decided to use text-shadow to implement it, though support is not as broad as I’d like to see. The primary pain in this is with the offset for the text-shadows. Due to the varying length of each line, you have to provide specific offsets for each line having the effect. This could a lot less painful if it were to be built with a preprocessor.

I’ve uploaded the demo over at Dabblet, JSFiddle, and CodePen. And for those who don’t have a browser that supports text-shadow, here’s a screenshot of the result:

shadows

One really neat side-effect of this approach is that because it uses shadows, it inherently gives off a responsive feel; in the demos above you can see that it extends as far left and right as its parent permits.

Update: Now Animated using @keyframes

Sometimes Chrome is the broken browser (Or, How Chrome failed me twice in one night)

For several years it’s been generally accepted by the web-development community that Internet Explorer is nothing more than a means by which developers are subjected a great deal of emotional and mental trauma. Well, that has changed in the last couple of versions, but most developers are still licking their slow-healing wounds.

One thing that bothers me though is how so many automatically feel as though these types of issues only exist with Internet Explorer, generally touting Google Chrome as the full-featured flawless alternative. Granted, Google has done an outstanding job with the Chrome browser, and I personally use it for most of my work, but Chrome is in no way special. It too is capable of causing a lot of upset – such was the case this evening for me.

I worked on a couple of marquee demos over the last few days which gave me another idea. I wanted to cover an element with its ::after pseudo-element, apply a transparent-to-black background on the pseudo-element, and then animate it off to the right using @keyframes. I didn’t want this to be visible as it moved off to the right, so I applied a parent element of the same dimensions, and set its overflow to hidden. Queue the tears.

Chrome 24, wouldn’t respond. It just sat there, frozen. I could have sworn I did something wrong, but the demo was so simple in its construction. Where was I going wrong? I ended up testing the same demo in Internet Explorer 10, and found it it immediately kicked off without any problems. So, back to Chrome – it turns out there was a question on Stack Overflow asked some time back regarding this very issue, which led me to news that Chrome had apparently fixed this in version 26 (unstable at the time of this writing).

Opening up Canary, I was pleased to see that my pseudo-elements were indeed being animated. Nice work Chrome! This was the first issue tonight where Internet Explorer 10 was working as expected, and Chrome was not. Next I noticed the pseudo-element bleeding out over the rounded edges of the parent; that’s not supposed to happen when you’ve got overflow:hidden set – right?

Back to Internet Explorer 10, I confirm that overflow:hidden does as it advertises, and the pseudo-element is not visible outside of its parents rounded corners – way to go Internet Explorer 10! But I still needed an unequivocal demonstration of this bug to confirm if Chrome was indeed busted, and misbehaving. That demo is now available online. As of today (January 20, 2013), this demo is broken in all versions of Chrome, but working in Internet Explorer 10 and Firefox.

So what’s the story here? The take-away is that Internet Explorer is no longer the browser it used to be. It’s a fully-qualified modern browser capable of some really killer things. It is well-built, and carries as much respect for standards as its competition. Chrome, on the other hand, did not come down to us from the gods of Mount Chrominus. It too is flawed in some ways, while brilliant in others.

Jumping on the one-browser-to-rule-them-all bandwagon doesn’t help the developer’s plight, it worsens it. Advocate standards, not browsers. Get behind good practices such as progressive-enhancement, feature-detection, and when necessary polyfills. Don’t champion a browser, champion the web.

Sometimes Chrome is the broken browser – it happens.

CHROME, Y U NO ANIMATE PSEUDO-ELEMENTS LIKE IE10?

CSS3 Marquees

I came across an old question on Stack Overflow that I answered years ago. It was asking how to scroll text, vertically, in a marquee-like fashion. At the time, I had answered that you would need to use Flash, or JavaScript/jQuery. I thought to myself, you would most certainly need to animate the top value of a positioned element, or maybe increase a negative margin or something.

Well, we live in a very different world today. And today, we have access to @keyframes, animation, and so much more in modern browsers. This got me wondering what type of simple marquee I could whip up in an instant (wound up playing with this for a little over an hour). What I came up with is posted below.

Take some time to read through the embedded comments, and play with the code. If you have any questions please feel free to post them in the comments below and I’ll assist as I am able.

Horizontal

Vertical

Use Vendor Prefixes Carefully

Vendor-prefixed properties and values in CSS are a beautiful thing; they allow you to do some really awesome stuff that would otherwise require a copy of Photoshop on your machine. In mere seconds you can whip up gradients, reflections, and even animations.

All of this is so appealing that people forget the fact that these are prefixed for a reason – they’re experiments, and should be viewed as such. That doesn’t mean you can’t use them, it just means you need to do so cautiously.

Don’t use these features in such a way that your page is severely broken without them – that’s not cool. Don’t use them in an unbalanced way either, providing prefixes for one browser but not for the others. And don’t use them in an anachronistic way, giving higher priority to prefixed experimental implementations over un-prefixed standardized implementations.

Often times I come across CSS that looks like this:

.gradientBox {
  background-image: linear-gradient(0deg, red, green);
  background-image: -moz-linear-gradient(0deg, red, green);
  background-image: -webkit-linear-gradient(0deg, red, green);
}

There are a few problems with this. For starters, only Firefox and Chrome/Safari are accounted for in the prefixes. It may very well be that Internet Explorer and Opera have provided an implementation under their own prefixes, -ms- and -o- respectively. You should provide for those as well.

Additionally, the unprefixed (which would be the standardized implementation) property is at the top, meaning it will be evaluated first, followed by the others. This means if you visit the page in a browser that supports both a -moz- prefix, and it’s unprefixed alternative, the un-prefixed implementation will be tossed out in favor of the experimental prefixed version – this isn’t cool.

So how should it look?

.gradientBox {
  background-image: -webkit-linear-gradient(0deg, red, green);
  background-image: -moz-linear-gradient(0deg, red, green);
  background-image: -ms-linear-gradient(0deg, red, green);
  background-image: -o-linear-gradient(0deg, red, green);
  background-image: linear-gradient(0deg, red, green);
}

The browser evaluates the rules from top to bottom. Internet Explorer will ignore any -webkit- properties, as well as any -moz- or -o- properties. If it supports the -ms- prefix, it will implement this rule. When it comes to the un-prefixed version, it will determine whether that value is supported or not. If it is not, it will be ignored, and the -ms- implementation will remain. Otherwise, the un-prefixed version will take precedence over the prefixed version. The same flow exists for the other major browsers.

But that’s a lot of writing, right? Fortunately we have a lot of great tools today that can reduce the effort on your page. From pre-processors like SASS and Compass to entire editors like Microsoft’s Visual Web Developer 2012, many options exist that will fill-out these values for you. We even have a great JavaScript option in -prefix-free which lets you write only the un-prefixed version – it will determine the appropriate prefix (if necessary) and insert it when the page is loaded.

Bottom line is this, we can enjoy these experimental features without breaking the web for people. If you’re going to use prefixed properties and values in CSS, do so wisely.

Free Web-Development Course

I have recently started offering a free web-development course both in person and online. The title of this meetup is “Home-Brew Web Development” and it takes place every Thursday evening at 7:30pm Easter Standard Time (unless otherwise stated). Each meetup is streamed live online at http://learn.sampson.ms, and archived on YouTube immediately afterwards.

We will start by learning HTML, followed by CSS. Eventually we will get into more advanced topics but I plan to keep it simple for now. This course is intended for those who have zero (or very little) experience in web-development, but are interested in it as a hobby, or a career-opportunity.

If you would like to receive regular updates regarding this course, future meetings, and more, you may subscribe to the newsletter via the link below. If at anytime you wish to stop receiving emails and stop attending the meetup, you’re totally free to go – it’s your call :)

Subscribe: http://eepurl.com/u_A61
Episodes: http://www.youtube.com/playlist?list=PL3IYnZmsleiXRVk1G-dcX4AJ_9kcSIO99

Sorting Arrays in JavaScript, from the Inside-Out.

Every now and then I come across questions on StackOverflow that require me to do a bit of thought-work. This particular question was asking to to take an array, such as ['a','b','c','d','e'], and flip it inside out, so that it becomes ['c','d','b','e','a']. I’m not a particularly mathematical person, so when I discover a difficult to discern pattern, I get excited – such was the case with the code below.

// Arrays to sort
var data = ["a","b","c","d","e"],
    info = ["a","b","c","d"];

// Sort array from inside-out ['a','b','c','d','e'] 
// Resulting in the following ['c','d','b','e','a']
function gut (arr) {
    
    // Resulting array, Counting variable, Number of items, 
    // initial Location
    var out = [], cnt, 
        num = arr.length, 
        loc = Math.floor(num/2);
    
    // Cycle through as many times as the array is long
    for (cnt = 0; cnt < num; cnt++)
        // Protecting our cnt variable
        (function () {
            // If our array has an odd number of entries
            if (num % 2) {
                // If on an odd iteration
                if (cnt % 2) {
                    // Move location forward
                    loc = loc + (+cnt); 
                } else {
                    // Move location backwards
                    loc = loc + (-cnt);  
                }
            // Our array has an even number of entries
            } else {
                // If on an odd iteration
                if (cnt % 2) {
                    // Move location backwards
                    loc = loc + (-cnt);
                } else {
                    // Move location forwards
                    loc = loc + (+cnt);
                }
            }
            // Push val at location to new array
            out.push(arr[loc]);
        })()
            
    // Return new array
    return out;
    
}

// Test with two arrays; even and odd sizes.
console.log(gut(data), gut(info));​

Which results in the following output:

["c", "d", "b", "e", "a"]
["c", "b", "d", "a"]

Perhaps you will find some use for it.

Active-Filtering of the Session List in Fiddler2

I use Fiddler2 daily – it’s one of the greatest debugging tools I’ve ever come across. You can hammer into the traffic coming and going across the tubes and tamper with the data as you like. You can substitute alternative local data in the place of remote server responses. You can modify headers on the fly. And this doesn’t even begin to scratch the surface of all you can do.

One of the problems I have is that, like many of you I’m sure, my browser is hardly ever doing one thing. Although I may be trying to debug a web-app, I may also be tied into my GMail inbox, streaming some music over Turntable, or watching the flow of tweets glide across @jonathansampson. All of these items cause sessions to be logged in Fiddler, adding a whole lot of noise to what I’m trying to work on.

So what do you do when you have specific hosts that you want to track? You make use of the Filters tab.

This highly-customizable tab will provide active filtering of the sessions coming across your screen. You can instruct it to show only intranet traffic, or only internet traffic. You can explicitly ignore particular hosts, or you can ignore everything but a select few. As my earlier summary of Fiddler didn’t begin to scratch the surface, neither does my explanation of this panel begin to touch on all that the Filter feature is capable of.

Have a look.

What I’ll be looking at here is the first part, the hosts section.

For starters, we need to click the “Use Filters” check-box to enable this feature. Now in my particular situtation all I want to see is anything that comes from a particular domain, such as microsoft.com. This would include any subdomains as well.

The first thing I will do is select “Show only Internet Hosts” from the first dropdown. From the second dropdown, I’ll select “Show only the following Hosts”. This enables the textarea below, which will take a series of expressions or explicit domains to watch for.

Insert *microsoft.com and you should see the textarea turn yellow, informing us that “Changes not yet saved.” At this point, click the Actions button to the top-right, and select “Run Filterset now”. If you already had sessions from your target domain in your session list, those should be all you see in there at this point.

From this you can infer how to go about blocking only particular domains, and various other things. You might even dare to venture into the rest of the filter options, creating a highly-customized instruction set. If you do, be sure to save your filter from the same Actions button we used to run the filterset.

I find this to be an enormously helpful feature, and I’m sure you will as well. Now if you’ll excuse me, I’ve got some work to do and very little noise preventing me from getting it done, thanks to Fiddler.

The big problem with Microsoft’s Flash whitelist browser sniffing

In The big problem with Microsoft’s Flash whitelist, ars author Peter Bright shared some of his concerns with the forthcoming Windows 8 Metro version of Internet Explorer 10. He states “it’s neither a full desktop browser nor a detectable mobile browser” after being shafted by Sony Pictures for not using a Flash-enabled browser.

Peter expressed concerns that since IE10 Metro uses the same user-agent string as IE10 on the desktop, developers won’t be able to detect which is which, and as such, they’ll assume you’re on a desktop and that your desktop supports Flash. As was pointed out in the article, HTML5 content is commonly reserved for mobile browsers – which the Metro IE10 is not.

At the bottom of Peter’s article was a byline that stated Peter “covers programming and software development, Web technology and browsers,” and as such I am saddened to see such a defense of user-agent sniffing and absolutely no mention of feature-detection.

User-agent sniffing, or “browser sniffing”, is the act of examining the user-agent string sent with requests to a server and inferring the browser or system’s abilities from that information alone. For instance, if your user-agent string contains a reference to “iPad”, I can safely assume you support HTML5.

The bottom line is that this practice is unprofessional, and naive. The user agent string is not an immutable property of the browser. It changes with each browser release, it changes with certain plugins being installed, and it changes by the authority of the user if they happen to be tampering with their developer tools (perhaps trying to get around poorly-coded sites that require certain user agent strings for access).

The jQuery documentation, while providing $.browser.msie for IE detection states “We recommend against using this property; please try to use feature detection instead.”

The Popular Yahoo Library, YUI, also contains the UA class for detecting the users browser, but they too plead with the user: “Do not fork for a browser if it can be avoided. Use feature detection when you can. Use the user agent as a last resort.”

One is forced to ask, why didn’t any of this make its way into Peter’s article? The article was instead an attack on Metro IE10 for not being an enabler to poor development practices. As Peter pointed out, he wasn’t able to watch his video because the site he was visiting was sniffing his user agent string. If Sony Pictures had been doing things the correct way, we wouldn’t have these problems.

Feature detection isn’t hard to do. In fact, regarding HTML5 video it’s a very trivial task:

if ( !!document.createElement("video").canPlayType ) {
    // Load HTML5
} else {
    // Go for Flash
}

That is all it takes. Not too hard right? It is even more trivial if you use a feature-detection suite like Modernizr to handle the heavy-lifting for you. No tampering with user-agent strings, no screwing up your parsing and thus breaking your user’s experience – not of that. Just giving the browser what the browser can handle.

When you assume you know what the browser is capable of without actually making some attempts, you ruin things for everybody. Just ask Karl Dubost, a web developer working with the Opera browser. He expressed some of his frustration when CFABank unnecessarily blocked Opera users from gaining access to their accounts.

Or perhaps Rey Bango, a jQuery team member and Developer Evangelist for Microsoft who shared the story of Paydirt, a wonderful service that prevented IE users from knowing how great their product was because they assumed IE wouldn’t work, even though IE9 and 10 handled their product very well.

This is what Peter’s complaint should have been – people are developing terrible sites. And it’s not just some kid at his house, it’s large companies like Sony Pictures. It’s a call for education, and it’s something we in the development community are working very hard to remedy.

Kudos to Microsoft for taking the actions they’ve taken. Having plugins in the browser leads to security risks, unnecessary battery usage, and so much more. Not to mention, if people build things using the native features available in modern browsers today (with the many great polyfills and fallbacks where necessary), we find the need for major plugins like Flash practically vanish.

I, for one, eagerly await the arrival of the plugin-free browser.

Of Dice, Dabblet, and CSS

I discovered dabblet.com some time back and never really spent much time there. Don’t get me wrong, it made a great first impression, however I am not super-talented in the CSS department, and it seems to be a tool for those who are.

I decided to return this evening and try my hand at creating some dice with nothing but CSS. I recently became a Potentate of the Rose, so this was a relevant and timely interest. After a couple hours of distracted back-and-forth, I finally had something pretty attractive.

While I don’t consider myself much of a CSS power-house, dabblet.com made the tedious process of building these die super-fun and very palatable. If you find yourself giving dabblet a run (and I suggest you do it), be sure to thank @leaverou for all of her hard work on such an awesome tool.

The final result can be seen here, or in the framed demo below.

Creating Your Own Custom jQuery Filters

Chances are you have probably used custom filters in jQuery from time to time to save on verbose selectors. For instance, if we wanted all of the buttons, selects, inputs, and textareas within a form we could do the following:

$("button, textarea, input, select", "#myForm");

You can see how that quickly piles up and gets a bit heavy. jQuery natively provides us with the :input filter which grabs all form elements:

$("#myForm :input");

While these both do the same thing, it’s far easier to call :input than it is to construct a large selector containing all of the particular form elements we can remember at the time. There is a bit of  a performance issue with things like :input though, since they have to cycle over all potential elements. That’s why it’s wise to limit our load by providing some context, in this case we’re looking only within #myForm.

While we can do a lot with what jQuery brings out-of-the-box, we’re capable of doing so much more using some of the tools it provides us with.

You’ve likely used .filter to sift through your elements before applying some effects:

$("div").filter(":visible").hide();

The filter method can take a string expression like :visible and determine which of the div elements meet its demands, and which don’t. Those that don’t will be dropped, and all remaining will have .hide called against them. This method can take a function as well:

$("div").filter(function(){
    return $(this).text() === "Foobar";
}).hide();

Here we are manually sifting through the elements based upon some examination of their properties. We return true or false, depending on whether the current element being evaluated has the text “Foobar” or not. This solution isn’t very flexible though, what if I wanted to check different things for different strings?

Fortunately jQuery exposes itself in such a way that we can extend its base filters and add our own.

Our focus from here will be on $.expr[":"]. Within the jQuery function ($) is an object called expr. This object has objects within, one of which is called “:”. This object is where we will place our new method, and provide the necessary functionality to determine which elements pass, and which fail.

$.extend($.expr[":"], {
    exactly: function(){
        return true;
    }
});

With nothing more than the above, we can already use our filter:

$("div:exactly");

Granted, it doesn’t do anything, but it doesn’t blow up in our face either! As is the case with most callback methods, the element currently being handled is referred to as this. With that, we could already perform some logic:

$.extend($.expr[":"], {
    exactly: function(){
        return $(this).text() === "Foobar";
    }
});

Of all the div elements we’re cycling over, only those whose text content loosely equals “Foobar” will be kept, while all others are discarded. But again, who wants to hard-code “Foobar” into the definition of the filter? Wouldn’t it be better if our filter worked like :contains in that it took some parameters?

It is at this point we need to look at the arguments passed to our function. We can do so by logging the arguments object from within:

$.extend($.expr[":"], {
    exactly: function(){
        console.log( arguments );
    }
});

$("div:exactly");

In our console we find the following:

[<div>​Hello World</div>​,   0, Array[4], NodeList[3]]
[<div>​Hello, World</div>​,  1, Array[4], NodeList[3]]
[<div>​Hello, World.</div>​, 2, Array[4], NodeList[3]]

My selector evaluated three div elements. The first argument passed to my function is the element itself. The second is the index of the element. Third is an array of details about the selector itself (more about that in a minute), and the last item is a NodeList of all elements being evaluated.

In this particular instance, our selector array looks like this:

[":exactly", "exactly", undefined, undefined]

We see it has a reference to the filter, the term used in the filter, and then two undefined values. If we were to modify our filter a bit to accept a parameter, we would see the following:

$("div:exactly(Foobar)");
[":exactly(Foobar)", "exactly", "", "Foobar"]

The first value is our entire selector. The second is our filter name, third in this case is empty (though if we wrapped our term in single quotes, this entry would be a single quote as the outer-most single-quotes would be removed from the last item in this array), and last is the actual parameter passed in. Armed with this knowledge, we can then finish our custom filter:

$.extend($.expr[":"], {
    exactly: function( element, index, details, collection ){
        return $(element).text() === details[3];
    }
});

At this point, we can now select any element based on its text value:

$("div:exactly(foo), p:exactly(bar)");

We now have a reusable solution to a common task.