Pangram verdict · v3.3
We believe that this entire text is human-written.
AI likelihood · overall
HumanArticle text · 1,446 words · 1 segments analyzed
The ebbs and flows of the web have gotten us to where we stand today. We simply wouldn’t have the web we do without the journey it has taken us to get here. However, some of the steps it has taken to get here have been interesting to say the least. CSS is how we style things on the web, but since its inception it has been made, on occasion, to wear a few more hats. It has taken on odd roles and picked up behaviours it probably ought not to have. Such is life. As I’ve detailed odd and context-specific HTML, this is a look at CSS largely outside the specifications. Browser-specific hacks, technology-scoped syntax, and engine-exclusive snippets forged from questionable circumstances, corporate complications, and esoteric implementations. Property Parsing width: 300px; *width: 250px; _width: 200px; -width: 200px; Most browsers, correctly, would treat a property prefixed with an asterisk as invalid. However, Internet Explorer 7 and earlier would treat it as valid. It was so famous it garnered the name ‘star hack’ for the shape of the asterisk. Likewise, when prefixing a property with an underscore or hyphen, only Internet Explorer 6 would treat it as valid. There were many more similar hacks used, the vast majority of which are best documented at the eponymous browserhacks.com. The main gist is that some browsers would incorrectly parse properties, selectors, and values, and that could be used for gain in an era where browser behaviour was rather varied. Limiting CSS to apply only in certain browsers with conditional comments in CSS files, such as could be done in HTML documents, wasn’t possible.1 Therefore, this exploitation of questionable parsing of what is and isn’t valid was commonplace for targeting specific browsers. Important background: red !interesting; Internet Explorer 7 and earlier would treat almost any textual string prefixed by an exclamation mark as !important. Most commonly, people would make use of this by writing !ie to have a style only override specificity in Internet Explorer. As far as Internet Explorer was concerned, the arbitrary !banana and the specced !important were the same, while other browsers correctly only accepted the latter. There was another related bug in Internet Explorer 6 and lower where a style declared later in the same block would overwrite an !important value. For example, here the colour would be black rather than white, as it should be: color: white !important; color: black; Document Level Browser Detection There were so many ways in which you could identify what browser was in use on a document level via CSS. Some examples include: In Internet Explorer 6 and earlier you could write * html {}. For only Internet Explorer 7 you could use *:first-child+html {}. Browsers other than Internet Explorer 7 support html > /**/ body {}. Early versions of Firefox would apply styles within body:empty {} (even when the body had contents). This approach was often messy to use, as it meant writing multiple descending selectors to try to target elements in specific browsers only. Clearfix .clearfix { zoom: 1; } Until version 8, Internet Explorer had a concept called hasLayout. An internal flag, it would designate whether an element was responsible for rendering itself (true) or if a parent element would be responsible for it (false). Naturally, this was an obtuse and confusing system. Some elements, such as <img>, <iframe>, and most things input-related, would intrinsically ‘have layout’. Other elements wouldn’t have layout, unless it was specifically given via specific CSS declarations being present. An element without layout could encounter weird margin and border behaviours, positioning complications, and general odd rendering and, most importantly, would cause parent containers to collapse when their children were floated. This caused all sorts of problems in an age where floating elements was the de facto way to lay out pages. The zoom property changes the size at which its target appears. With a value of 1, the target appears at its existing size. This may seem useless, but zoom gives an element layout, so it would be used as a simple way to do so without otherwise changing an element’s visual appearance. Hand Cursor cursor: pointer; cursor: hand; Prior to Internet Explorer 6, Internet Explorer didn’t respect the pointer value for the cursor property. Instead, it only supported the non-standard hand value, which provided a pointing hand. Therefore, sites would commonly write both values in their CSS with the expectation that cursor: hand would be considered invalid in browsers other than Internet Explorer, thus prompting them to use pointer while Internet Explorer uses hand. CSS Expressions top: expression(eval(document.documentElement.scrollTop)); Formally called ‘Dynamic Properties’, CSS expressions were a way to execute JavaScript in CSS. It was non-standard behaviour introduced in Internet Explorer 5 to patch up lagging styling capabilities, such as missing support for position: fixed (which the above snippet addresses), or min-width and max-width, among others. This made making layouts rather difficult. CSS Expressions were hacky and awkward while exposing a lot of complexity. You could go as far as to change what styles were applied based on the time of day using Date(). CSS expressions were constantly re-evaluated, making them extremely performance taxing. As was noted by Steve Souders on the Yahoo! Developer Network blog: The problem with expressions is that they are evaluated more frequently than most people expect. Not only are they evaluated when the page is rendered and resized, but also when the page is scrolled and even when the user moves the mouse over the page. Microsoft ended support for them with Internet Explorer 8, as announced in their dramatically titled post ‘Ending Expressions’. Filters Internet Explorer had a number of iffy behaviours and lagged behind other browsers for many visual effects, even regarding basic properties like opacity. Thus, Microsoft brought in bespoke filter functionality. Filters used DirectX-based components of Windows, far away from web platform standards. Internet Explorer first introduced its filter functionality with version 4. The syntax was rather simple, with an example of lowering an element’s opacity looking like this: filter: alpha(opacity=50); It was far from perfect but allowed addressing many of Explorer’s shortcomings. Filters required that an element had layout and also annoyingly stripped ClearType font anti-aliasing for small text, making it look jagged. Sometimes they’d cause issues with interactivity, too. In version 5.5 filter syntax became more complex, looking like this: filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50); Note the presence of DX referring to DirectX. Filters could even be animated. In the last update to filter functionality, Microsoft vendor-prefixed their filter property in version 8 to better comply with CSS standards. They also made it so that filters would not strip font anti-aliasing, and it became necessary to wrap the value in quotes: -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=50)"; -ms-filter was finally removed with Internet Explorer 10. This removal extended to Internet Explorer’s legacy modes too. By version 10’s release, most popular uses for filters had received support from the browser, such as the opacity property which was added in version 9. Aside from opacity, two of the other very common uses for Explorer’s filter capabilities were handling transparent PNG images and applying gradients. Transparent sections of PNGs in Internet Explorer 6 and earlier were replaced with a grey background. Even in later versions, PNGs could encounter issues usually related to gamut. Therefore, people would often load images via AlphaImageLoader: filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png'); Gradients would be applied with filter as an alternative to using background images (linear-gradient() would not receive support until Internet Explorer version 10). filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='red', endColorstr='green', GradientType=0); People would often implement simple reusable filters for commonly encountered situations using the aforementioned CSS Expressions functionality. body { scrollbar-face-color: #333333; scrollbar-highlight-color: #666666; scrollbar-3dlight-color: #000000; scrollbar-darkshadow-color: #000000; scrollbar-shadow-color: #111111; scrollbar-arrow-color: red; scrollbar-track-color: #222222; } Internet Explorer version 5.5 introduced the ability to customise the appearance of scrollbars. The above scrollbar styles applied in Internet Explorer 11. For the arrow buttons and thumb, face-color set background, highlight-color set the inner left highlight, 3dlight-color set the outer right highlight, darkshadow-color set the inner right shadow, shadow-color set the inner right shadow, and arrow-color set the arrow icons themselves. track-color obviously set the scrollbar track. There were even full applications for generating the styles. Much like today, styling scrollbars was considered somewhat gaudy and over-the-top, so it was mostly used for minor tweaks in professional contexts. The functionality was of course utilised to its fullest potential by people customising their MySpace profiles. HTML Components .item { behavior: url(csshover.htc); } HTML Components (not to be confused with contemporary Web Components) were an Internet Explorer exclusive feature added in version 5 and expanded greatly in version 5.5, which allowed attaching scripting logic to HTML elements via CSS. Though many languages were supported, JavaScript was almost always used.