Category Archives: Just for fun

Emulation Accuracy in Internet Explorer

Early preview versions of Internet Explorer 11 lacked Emulation features that we saw in Internet Explorer 9 and 10. When Windows 8.1 shipped, Internet Explorer 11 was found to have the Emulation features shipped with it. These tools are helpful, though they can be misleading at times.

My general workflow in the past when using these tools goes like this: A user reports an issue in Internet Explorer x. I instruct the latest version of Internet Explorer to emulate the reported version. If I encounter the same issue, I can debug using the modern version of Internet Explorer. If emulation does not reveal the same issue, I need to load up a virtual machine, or use a service like BrowserStack.

The problem with these tools is that it’s not entirely clear where the line of reliability resides. To what degree this emulation replicates the native experience is unknown (to me, at least). Due to this, I’ve decided to do a deep dive into Emulation and see just how reliable it is, and in which areas.

Computed Styles

The first dive wasinto Computed Styles. Does Internet Explorer generate the same computed styles as IE10 and IE9 when it is emulating those versions? Surprisingly, yes. Granted, I’m running instances of IE10 and IE9 in a Virtual Machine (compliments of modern.ie), so that should be considered. Also other important thing to note is that this pass-through assumes Standards Mode.

The comparison tables are being maintained in a Google Docs spreadsheet. Click the preview below for the full view.

comparison.table

Window Object

My next focus was on cycling over enumerable properties on the window object and laying those out for comparison. A cursory glance of this next table will reveal that Internet Explorer 11 emulates the window object from IE9 and IE10 very well. Granted, there are some very clear examples of where it brought along a couple extra methods and properties.

comparison.table.window

It’s worth noting that this particular table had to be done a couple of times. Some of these members don’t attach themselves to the window object until certain actions are performed. For instance, this table is front-loaded with a bunch of BROWSERTOOLS members that are pushed onto the window object when various portions of the developer tools are opened. Other members, such as $0, don’t exist until you perform an action like selecting an element in the DOM Explorer.

More on GIFs and Painting in Internet Explorer

About a week ago I wrote a post demonstrating the use of UI Responsiveness functionality in Internet Explorer 11 to determine how the browser handles animated GIFs in various states. This post was a fairly well-received so I wanted to expand a bit more upon it and cover a few more scenarios.

For the most recent round of testing, I setup a simple interval to change the className of the body element every few seconds. This, in turn, affects the placement and layout of a single image element within the document.

(function () {

  "use strict";

  var states = ["", "opacity", "visibility", "offscreen", "perpendicular"],
      container  = document.body,
      cycles = 0,
      nextState;

  function advanceState () {
    // Advance to next array index, or return to start
    nextState = states[++cycles % states.length];
    // Indicate a new performance mark in our developer tools
    performance.mark(nextState ? "Starting " + nextState : "Restarting");
    // Update the body class to affect rendering of image
    container.className = nextState;
  }

  setInterval(advanceState, 3000);

}());

I used the performance.mark method to add my own indicators in the performance graphs to help me identify when the demo was transitioning into a new state. These performance marks are represented in Internet Explorer by small upside-down orange triangles.

performance.ticks

Let’s walk through each of these triangles left to right, discussing the state they represent.

GIF Untouched

This state is represented by all activity to the left of the first performance mark. Not much needs to be said – Internet Explorer continued to paint the GIF as it sat animated on the screen.

performance.ticks.0

Setting GIF Opacity

This step is represented by all activity between the first and second performance marks. In this step, the image element has its opacity property set to 0. Even though the image is no longer visible, the browser continued repainting the region occupied by the image element.

performance.ticks.1

Setting GIF Visibility

This step is represented by all activity between the second and third performance marks. In this step, the image element has its visibility property set to hidden. Once the visibility property was set to hidden, the browser made one final repaint (presumably to hide the element) and no further paint events took place during the duration of this state.

Of relevance here is that the hidden attribute on the image itself has the same effect. When this attribute is present on the element, Internet Explorer will cease to repaint that elements occupied region.

performance.ticks.2

Setting GIF Outside of View

This step is represented by all activity between the third and fourth performance marks. In this step, the image element is positioned absolutely at top -100% left -100%. In spite of the fact the element is positioned outside of the viewport itself, the browser continued to run paint cycles.

performance.ticks.3

Setting GIF Orientation Perpendicular to Viewport

This step is represented by all activity between the fourth and fifth performance marks (the fifth mark is the ‘Restarting’ mark). In this step, the image is rotated using the transform property so as to set it at a right angle to the viewport, effectively hiding its content from the viewer. This orientation did not affect the browser paint cycle, and Internet Explorer continued repainting the region occupied by the image element.

performance.ticks.4

Conclusion

As a general rule, it appears Internet Explorer will run paint cycles for every animated GIF in the document, unless that element has its visibility property set to hidden. This is fairly reasonable, since setting visibility to hidden is the only explicit way to tell the browser not to render the element. Keep this in mind when performance is of key importance.

After running through and investigating this further I was curious what the same test would reveal in Chrome. I was pleased to see that Chrome would cease to paint for the opacity, visibility, and offscreen configurations. No performance marks are revealed in Chrome’s developer tools, but you can identify the timer functions by the presence of a small orange mark.

performance.ticks.chrome

Milestone Hangout 0.2.0 Reached

For months I’ve been doing weekly Hangouts where I walk through the HTML Specification, and most recently the CSS 2.1 Specification. This has served as a means by which I can help others get a better understanding of the core technologies behind solid web development, as well as an opportunity for myself to retrace some of the forgotten roots of these ubiquitous languages.

Recently I wrapped up episode 20, or 0.2.0, which covered Counters, Automatic Numbering, Lists, and Backgrounds in CSS. It was a great episode since I had never actually used counters in CSS to begin with. This was one of the benefits of retracing those old roots – there is a surprisingly amount of stuff that isn’t common enough that I ever learned about it in the past.

After roughly 21 hours of live hangouts I am about to start a series of JavaScript hangouts. These will take place at the same standard time, Thursday evenings at 7:30pm Eastern. If you’re new to web development, or don’t feel all that confident with JavaScript, please feel free to attend. You can login with your Twitter handle and ask questions in realtime.

If you want to drop through some of the older hangouts, they’re organized in two playlists:

Browsers – Broken By Design

I set out a few hours ago to write about a problem I had experienced in Safari, Chrome, Firefox, and Internet Explorer. Opera worked as I expected, which had me convinced the other vendors merely dropped the ball, and shipped partial implementations for the :visited and :link pseudo-classes.

My CSS was very simple:

:link {
    color: white;
    background: red;
}

:link::before {
    content: "Pseudo: ";
}

A color set for unvisited links, followed by some content in the ::before pseudo element on all unvisited links. So when I dropped in two links (one visited, one not) I expected to see the following:

image00 copy

Instead, what I saw was a litter of inconsistent results between Chrome, Safari, Internet Explorer, Firefox, and Opera. The above image came from Opera. It performed exactly as I suspected. The others, not so much.

Chrome and Firefox gave similar results; both set “Pseudo” as a virtual first-child of both anchors (though I only asked to have it on unvisited links), and leaked the background color from :link into :visited.

Internet Explorer did better than Chrome and Firefox; it preserved the “pseudo” text, but left the background of the visited link untouched. I was still very perplexed as to why it was spilling values from :link over into :visited.

You can observe something interesting in Internet Explorer – :visited links start visually identical to :link links, but are transitioned into their :visited state immediately thereafter. Setting a transition on all links reveals the change when the document loads:

a {
    transition: background 10s;
}

You’ll see the :link links remain unchanged but :visited links slowly adopt their end style. This is not the case for Chrome, Firefox, Opera, or Safari.

Safari appeared to be the most broken of them all. It duplicated everything. Further, I attempted to set additional styles to :visited, and it completely ignored them.

Discovering History

I found it incredible that all of these browsers, with the exception of Opera, would get this so wrong. So like any good developer I took to the web to see who else might be complaining about this, which is when I came across a Stack Overflow post suggesting this was somehow related to security concerns.

This offered another search vector; security issues. That was the needed catalyst for opening up a fascinating story about yet another creative attempt by developers to put their nose where it may not belong – in the client browser’s history.

Browsers typically style links with a default color to indicate whether it is a visited link or not. We’ve all seen those blue and purple links before – they’ve become quite at home on the web. Somebody got the (seriously) brilliant idea to create anchors ad hoc, and use getComputedStyle to see if the links represented visited or unvisited locations.

Mozilla reports that you could test more than 200,000 urls every minute with this approach. As such, you could – with a great deal of accuracy – fingerprint the user visiting your site based on the other urls they have visited; and browser history runs deep.

Scorched Earth Solution

The solution implemented by Firefox (and apparently others) was to greatly reduce the presence of visited links. They started by instructing functions like getComputedStyle and querySelectorAll to lie (their words, not mine) about their results. Sure enough, a simple check confirms that though my :visited links have a different font color than :link links, getComputedStyle says they’re the same rgb value.

Mozilla’s Christopher Blizzard continues with a very key point (emphasis added):

You will still be able to visually style visited links, but you’re severely limited in what you can use. We’re limiting the CSS properties that can be used to style visited links to color, background-color, border-*-color, and outline-color and the color parts of the fill and stroke properties. For any other parts of the style for visited links, the style for unvisited links is used instead. In addition, for the list of properties you can change above, you won’t be able to set rgba() or hsla() colors or transparent on them.

And there it was, the explanation that tied all of the seemingly broken pieces together. The browser would instruct :visited to share property values with :link. The browsers aren’t broken; they were designed to fail.

Test Confirmations

I wanted to explore the now-understood implementation a bit further, so I tried a few things. Querying the DOM for :visited links (expecting 1 of 2) was my first decision. I also queried the DOM for :link as well – expecting 2 due to the new security:

Browser Number of :visited Number of :link
Chrome 0 2
Firefox 0 2
Internet Explorer 0 2
Safari 0 2
Opera 1 2

Nearly all of the browsers report no :visited link, with the exception of Opera. All browsers report a total of 2 links when querying :link.

So it seems like you can still get a list of visited sites in Opera. Internet Explorer, Firefox, Chrome, and Safari all prevented the exploit from being carried out. But one thing about Internet Explorer intrigued me; remember the transitioning I spoke of earlier?

Internet Explorer Still Vulnerable?

I noticed that if I set transition: background 10s on anchors in Internet Explorer you would slowly see all visited links slowly tween into their end state. Transitions fire the transitionend event when they complete, so could we still get the user’s visited links in Internet Explorer?

The CSS to test this is very simple:

a { transition: background .01s }
:link { background: red }

And the following JavaScript:

/* Anchor var, fragment, and array of guesses */
var anchor;
var fragment = document.createDocumentFragment();
var websites = [
    'http://bing.com',
    'http://google.com',
    'http://jquery.com',
    'http://appendto.com',
    'http://stackoverflow.com'
];

/* Listen for completed transitions */
document.addEventListener("transitionend", function (event){
    console.log(event.target.href);
}, false);

/* Create a link for each url */
websites.forEach(function(url){
    anchor = document.createElement("a");
    anchor.setAttribute("href", url);
    anchor.innerHTML = url;
    fragment.appendChild( anchor );
});

/* Add our document fragment to our DOM */
document.body.appendChild(fragment);

Immediately upon being added to the DOM our :visited anchors will start to transition away from looking like a :link anchor. Once that transition is complete, we learn what the URL is, and confirm that the user has visited that site.

Closing Thoughts

I was reminded today just how exciting our industry is. People are constantly experimenting, learning new things, and sharing that knowledge. Industry experts, developers, designers, and browser vendors are always working to shift and adjust in light of the ever-evolving web.

Although the CSS2.1 Specification says something, that doesn’t make it so – even if the feature is 15 years old. If the ends justify the means, browser vendors will (and did) fire-bomb their own code-base to protect the end user.

Finally, we’re all in this together; we ought to work together. Microsoft launched the @IEDevChat twitter account not too long ago to assist developer’s who are attempting to follow web-standards. Then even organized a group of developers who wanted to volunteer and help build a better web; you can find (and join) it online at http://useragents.ie.

I’m sure there’s more history here that I’ve yet to discover, but what I have seen is enough to pique my interest. If you have anything else to share, or can contribute to the vulnerability test approach above, please leave a comment below. I may swing back around and check out the other browsers later on.

HTML Hangout Concludes after 16 Hours

For months I have been doing a weekly HTML Hangout where I work, slowly, through the W3C Specification for HTML5. I’m pleased to say that after 15 videos, and 16 hours, we’ve gotten to the point where we can progress on to bigger and better things.

HTML is now taken care of, and we will now move on to making this a weekly CSS Hangout. If you’d like to watch the HTML5 lessons, you can do so by viewing this playlist of YouTube: http://www.youtube.com/playlist?list=PL3IYnZmsleiXRVk1G-dcX4AJ_9kcSIO99.

If you’d like to join us in the future, simply show up to http://learn.sampson.ms on Thursdays at 7:30PM Eastern. Broadcast usually starts about 10 minutes early, and we open up the last 10-15 minutes for questions and answers.

Progress Dots

From time to time I need to throw together a small script to do something relatively simple. Today I had to write something that would animate a series of dots. You’ve seen it, those little lines of dots that grow and shrink to give indication that something, somewhere is happening.

It’s a relatively straight forward script, so I’ll just drop it in here with comments:

(function () {

    "use strict";

    // Find #dots, run setDots every 500ms, define your dot, and set size limit
    var dots = document.getElementById("dots"),
        loop = setInterval(setDots, 500),
        _dot = ".",
        size = 3;

    function setDots () {
        // #dots will be truncated when limit is reached, otherwise grows by one
        dots.innerHTML = (dots.innerHTML.length >= size) ? _dot : (dots.innerHTML + _dot);
    }

}());

It’s worth noting that you could probably whip up something similar with CSS alone using pseudo-elements, animation, @keyframes, and content, or even animating a sprite’s location on a background. Of course browser support would be far more limited.

Visualizing :hover Propagation

The :hover pseudo-class can be tossed into a CSS selector to target the state of the element when the user’s cursor is currently positioned over the element. Due to the hierarchical structure of the DOM, anytime you activate the :hover state of an element, you activate it for all ancestral elements too. Wanting a quick illustration for this, I took to JSFiddle.

http://jsfiddle.net/FwKqq/6/show/

Polyfill for Reversed Attribute on Lists

Lists in HTML typically appear in decimal fashion, starting from 1 and going to n. Sometimes these are instructed to appear in reversed order via the reversed boolean attribute on the ol element.

<ol reversed>
    <li>I am number two.</li>
    <li>And I am number one.</li>
</ol>

Some browsers don’t understand the reversed attribute, and thus will not reverse the list. Although you cannot reverse the entire list in some browsers with this attribute, you can manually override the value associated with each list item in most browsers via the value attribute.

<ol>
    <li value="2">I am number two.</li>
    <li value="1">And I am number one.</li>
</ol>

Using jQuery, we can quickly create a short polyfill that will give us reversed functionality in browsers where it’s not natively understood.

(function () {
    if ( $("<ol>").prop("reversed") === undefined ) {
        $("ol[reversed]").each(function () {
            var $items = $(this).find("li");
            $items.attr("value", function ( index ) {
                return $items.length - index;
            });
        });
    }
}());

The code should be fairly straight-forward, but let me explain what is going on just to be on the safe side.

We start with an IIFE (Immediately Invoked Function Expression) which runs our code instantly, as well as keeps all declared variables out of the global namespace.

Next we kick things off with a quick feature-test on a freshly-made ol. In browsers that understand the reversed property, the default value is false. In other browsers, the property is undefined.

We then grab a collection of all lists that have the reversed attribute. Next we cycle over this collection of lists, assigning the list items from each iteration to the variable $items.

We then take the $items jQuery collection and begin an implicit loop setting the value attribute of each item in the collection to collection.length - itemIndex. If there are five items in the list, and we’re on index 0 (first item), five will be returned as the value. When we enter the second iteration, and the index is 1, (5-1) will be returned, resulting in a value of 4.

Voila, we have polyfilled reversed. There are some shortcomings; this won’t work on lists created after this code runs. You could however put this logic into a function declaration and call it after the DOM has been updated asynchronously, so as to handle any new lists that might have populated the document.

One very important note when using jQuery as a means to polyfill older browsers, you will have to use jQuery 1.8.3 or below. Around the release of jQuery 1.9, a lot of antiquated code was removed that once propped up older browsers. jQuery 1.9 and forward are meant for modern browsers, and as such they will fail in carrying your polyfilled functionality back to older browsers like Internet Explorer 6, and its contemporaries.