{"rowid": 154, "title": "Diagnostic Styling", "contents": "We\u2019re all used to using CSS to make our designs live and breathe, but there\u2019s another way to use CSS: to find out where our markup might be choking on missing accessibility features, targetless links, and just plain missing content. \n\nNote: the techniques discussed here mostly work in Firefox, Safari, and Opera, but not Internet Explorer. I\u2019ll explain why that\u2019s not really a problem near the end of the article \u2014 and no, the reason is not \u201ceveryone should just ignore IE anyway\u201d.\n\nBasic Diagnostics\n\nTo pick a simple example, suppose you want to call out all holdover font and center elements in a site. Simple: you just add the following to your styles.\n\nfont, center {outline: 5px solid red;}\n\nYou could take it further and add in a nice lime background or some such, but big thick red outlines should suffice. Now you\u2019ll be able to see the offenders wherever as you move through the site. (Of course, if you do this on your public server, everyone else will see the outlines too. So this is probably best done on a development server or local copy of the site.)\n\nNot everyone may be familiar with outlines, which were introduced in CSS2, so a word on those before we move on. Outlines are much like borders, except outlines don\u2019t affect layout. Eh? Here\u2019s a comparison.\n\n\n\nOn the left, you have a border. On the right, an outline. The border takes up layout space, pushing other content around and generally being a nuisance. The outline, on the other hand, just draws into quietly into place. In most current browsers, it will overdraw any content already onscreen, and will be overdrawn by any content placed later \u2014 which is why it overlaps the images above it, and is overlapped by those below it.\n\nOkay, so we can outline deprecated elements like font and center. Is that all? Oh no.\n\nAttribution\n\nLet\u2019s suppose you also want to find any instances of inline style \u2014 that is, use of the style attribute on elements in the markup. This is generally discouraged (outside of HTML e-mails, which I\u2019m not going to get anywhere near), as it\u2019s just another side of the same coin of using font: baking the presentation into the document structure instead of putting it somewhere more manageable. So:\n\n*[style], font, center {outline: 5px solid red;}\n\nAdding that attribute selector to the rule\u2019s grouped selector means that we\u2019ll now be outlining any element with a style attribute.\n\nThere\u2019s a lot more that attribute selectors will let use diagnose. For example, we can highlight any images that have empty alt or title text.\n\nimg[alt=\"\"] {border: 3px dotted red;}\nimg[title=\"\"] {outline: 3px dotted fuchsia;}\n\nNow, you may wonder why one of these rules calls for a border, and the other for an outline. That\u2019s because I want them to \u201cadd together\u201d \u2014 that is, if I have an image which possesses both alt and title, and the values of both are empty, then I want it to be doubly marked.\n\n\n\nSee how the middle image there has both red and fuchsia dots running around it? (And am I the only one who sorely misses the actual circular dots drawn by IE5/Mac?) That\u2019s due to its markup, which we can see here in a fragment showing the whole table row.\n\n\nempty title\n\n\"\"\n\"comical\"\n\n\nRight, that\u2019s all well and good, but it misses a rather more serious situation: the selector img[alt=\"\"] won\u2019t match an img element that doesn\u2019t even have an alt attribute. How to tackle this problem?\n\nNot a Problem\n\nWell, if you want to select something based on a negative, you need a negative selector.\n\nimg:not([alt]) {border: 5px solid red;}\n\nThis is really quite a break from the rest of CSS selection, which is all positive: \u201cselect anything that has these characteristics\u201d. With :not(), we have the ability to say (in supporting browsers) \u201cselect anything that hasn\u2019t these characteristics\u201d. In the above example, only img elements that do not have an alt attribute will be selected. So we expand our list of image-related rules to read:\n\nimg[alt=\"\"] {border: 3px dotted red;}\nimg[title=\"\"] {outline: 3px dotted fuchsia;}\nimg:not([alt]) {border: 5px solid red;}\nimg:not([title]) {outline: 5px solid fuchsia;}\n\nWith the following results:\n\n\n\nWe could expand this general idea to pick up tables who lack a summary, or have an empty summary attribute.\n\ntable[summary=\"\"] {outline: 3px dotted red;}\ntable:not([summary]) {outline: 5px solid red;}\n\nWhen it comes to selecting header cells that lack the proper scope, however, we have a trickier situation. Finding headers with no scope attribute is easy enough, but what about those that have a scope attribute with an incorrect value?\n\nIn this case, we actually need to pull an on-off maneuver. This has us setting all th elements to have a highlight style, and then turn it off for the elements that meet our criteria.\n\nth {border: 2px solid red;}\nth[scope=\"col\"], th[scope=\"row\"] {border: none;}\n\nThis was necessary because of the way CSS selectors work. For example, consider this:\n\nth:not([scope=\"col\"]), th:not([scope=\"row\"]) {border: 2px solid red;}\n\nThat would select\u2026all th elements, regardless of their attrributes. That\u2019s because every th element doesn\u2019t have a scope of col, doesn\u2019t have a scope of row, or doesn\u2019t have either. There\u2019s no escaping this selector o\u2019 doom!\n\nThis limitation arises because :not() is limited to containing a single \u201cthing\u201d within its parentheses. You can\u2019t, for example, say \u201cselect all elements except those that are images which descend from list items\u201d. Reportedly, this limitation was imposed to make browser implementation of :not() easier.\n\nStill, we can make good use of :not() in the service of further diagnosing. Calling out links in trouble is a breeze:\n\na[href]:not([title]) {border: 5px solid red;}\na[title=\"\"] {outline: 3px dotted red;}\na[href=\"#\"] {background: lime;}\na[href=\"\"] {background: fuchsia;}\n\n\n\nHere we have a set that will call our attention to links missing title information, as well as links that have no valid target, whether through a missing URL or a JavaScript-driven page where there are no link fallbacks in the case of missing or disabled JavaScript (href=\"#\").\n\nAnd What About IE?\n\nAs I said at the beginning, much of what I covered here doesn\u2019t work in Internet Explorer, most particularly :not() and outline. (Oh, so basically everything? -Ed.)\n\nI can\u2019t do much about the latter. For the former, however, it\u2019s possible to hack your way around the problem by doing some layered on-off stuff. For example, for images, you replace the previously-shown rules with the following:\n\nimg {border: 5px solid red;}\nimg[alt][title] {border-width: 0;}\nimg[alt] {border-color: fuchsia;}\nimg[alt], img[title] {border-style: double;}\nimg[alt=\"\"][title],\nimg[alt][title=\"\"] {border-width: 3px;}\nimg[alt=\"\"][title=\"\"] {border-style: dotted;}\n\nIt won\u2019t have exactly the same set of effects, given the inability to use both borders and outlines, but will still highlight troublesome images.\n\n\n\nIt\u2019s also the case that IE6 and earlier lack support for even attribute selectors, whereas IE7 added pretty much all the attribute selector types there are, so the previous code block won\u2019t have any effect previous to IE7.\n\nIn a broader sense, though, these kinds of styles probably aren\u2019t going to be used in the wild, as it were. Diagnostic styles are something only you see as you work on a site, so you can make sure to use a browser that supports outlines and :not() when you\u2019re diagnosing. The fact that IE users won\u2019t see these styles is irrelevant since users of any browser probably won\u2019t be seeing these styles.\n\nPersonally, I always develop in Firefox anyway, thanks to its ability to become a full-featured IDE through the addition of extensions like Firebug and the Web Developer Toolbar.\n\n\nYeah, About That\u2026\n\nIt\u2019s true that much of what I describe in this article is available in the WDT. I feel there are two advantages to writing your own set of diagnostic styles.\n\n\n\tWhen you write your own styles, you can define exactly what the visual results will be, and how they will interact. The WDT doesn\u2019t let you make its outlines thicker or change their colors.\n\tYou can combine a bunch of diagnostics into a single set of rules and add it to your site\u2019s style sheet during the diagnostic portion, thus ensuring they persist as you surf around. This can be done in the WDT, but it isn\u2019t as easy (and, at least for me, not as reliable).\n\n\nIt\u2019s also true that a markup validator will catch many of the errors I mentioned, such as missing alt and summary attributes. For some, that\u2019s sufficient. But it won\u2019t catch everything diagnostic styles can, like empty alt values or untargeted links, which are perfectly valid, syntactically speaking.\n\n\nDiagnosis Complete?\n\nI hope this has been a fun look at the concept of diagnostic styling as well as a quick introduction into possibly new concepts like :not() and outlines. This isn\u2019t all there is to say, of course: there is plenty more that could be added to a diagnostic style sheet. And everyone\u2019s diagnostics will be different, tuned to meet each person\u2019s unique situation.\n\nMostly, though, I hope this small exploration triggers some creative thinking about the use of CSS to do more than just lay out pages and colorize text. Given the familiarity we acquire with CSS, it only makes sense to use it wherever it might be useful, and setting up visible diagnostic flags is just one more place for it to help us.", "year": "2007", "author": "Eric Meyer", "author_slug": "ericmeyer", "published": "2007-12-20T00:00:00+00:00", "url": "https://24ways.org/2007/diagnostic-styling/", "topic": "process"}