From 5d5cd2da1e4e34d8e4bbc3ff12d06f9a32a33297 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 12 Oct 2011 11:47:00 -0700 Subject: [PATCH 01/23] Pretty things up. Better reset for :after elements, lighten up colors for better contrast. --- README.md | 6 ++++- debugCSS.css | 67 +++++++++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index f5829a4..775d5e3 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,8 @@ Each condition is specified in three areas: - Setting up the :after area for display (trying to reset common styles like colors, font sizes, etc). - Specifying the color severity (green, yellow, red) and content (which is the error or warning message to be displayed). - - Creating the outline around the offending element according to it's color severity. \ No newline at end of file + - Creating the outline around the offending element according to it's color severity. + +Install +--- +Visit [http://yahoo.github.com/debugCSS/](http://yahoo.github.com/debugCSS/) to install the bookmarklet. \ No newline at end of file diff --git a/debugCSS.css b/debugCSS.css index b8b3822..0ac164a 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -18,7 +18,12 @@ broken, malformed or legacy (X)HTML. Not all "errors" are created equally, so they are color coded to highlight severity. Green is "probably not a big problem", yellow is "worth looking at" and red is "you really should fix - this." + this." Red severity is currently not used, but can be made available for + future revisions. + + Red: #FF8888; + Yellow: #FFFF88; + Green: #88FF88; */ /******************/ @@ -84,8 +89,12 @@ marquee:after { display: block; font-family: helvetica; font-size: 12px; - font-weight: normal; + font-style: normal; + font-weight: bold; + line-height: 1.3em; + padding: .1em .3em; position: absolute; + text-decoration: none; text-transform: none; z-index: 99999; } @@ -97,43 +106,43 @@ marquee:after { */ table:not([summary]):after { - background: green; + background: #88FF88; content: 'Should you have a SUMMARY attribute on your TABLE?'; } table > tr:after { - background: yellow; + background: #FFFF88; content: 'TABLE does not have a TBODY.'; } table th:not([scope]):after { - background: green; + background: #88FF88; content: 'Should TH have a SCOPE attribute (ROW or COL)?.'; } table thead td:after { - background: green; + background: #88FF88; content: 'Cells in THEAD should be TH.'; } table > tbody:first-child:after { - background: green; + background: #88FF88; content: 'Do you need a THEAD or TFOOT?'; } table > tbody + tfoot:after { - background: yellow; + background: #FFFF88; content: 'TBODY should come after TFOOT.'; } table > tr:first-child:last-child:after, table > tbody > tr:first-child:last-child:after { - background: green; + background: #88FF88; content: 'Only one TR in TABLE. Are you using it for layout?'; } table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption):after { - background: yellow; + background: #FFFF88; content: 'Only THEAD/TFOOT/TBODY/COLGROUP/CAPTION/TR can be children of a TABLE'; } @@ -143,18 +152,18 @@ table[border]:after, table[cellpadding]:after, table[cellspacing]:after, table[width]:after { - background: yellow; + background: #FFFF88; content: 'Element has inline style.'; } img:not([alt]):after { - background: yellow; + background: #FFFF88; content: 'Image does not have an ALT attribute.'; } a[href="#"]:after, a:not([href]):after { - background: yellow; + background: #FFFF88; content: 'Anchor tag is # or does not exist - does not degrade gracefully.'; } @@ -162,22 +171,22 @@ a[href*=javascript\:]:after, a[onclick]:after, a[onmouseover]:after, a[onmouseout]:after { - background: yellow; + background: #FFFF88; content: 'Inline JS on anchor.'; } label:not([for]):after { - background: yellow; + background: #FFFF88; content: 'Should LABEL have a FOR attribute?'; } nav:not([role]):after { - background: yellow; + background: #FFFF88; content: 'NAV element should have a ROLE attribute.'; } div[role="img"]:not([aria-label]):after { - background: yellow; + background: #FFFF88; content: 'DIV used as image should have ARIA-LABEL.'; } @@ -195,58 +204,58 @@ html[xmlns] a h3:after, html[xmlns] a h4:after, html[xmlns] a h5:after, html[xmlns] a h6:after { - background: yellow; + background: #FFFF88; content: 'Block level element within inline element.'; } ol > *:not(li):after, ul > *:not(li):after { - background: yellow; + background: #FFFF88; content: 'Only LIs can be children of UL or OL'; } dl > *:not(dt):not(dd):after { - background: yellow; + background: #FFFF88; content: 'Only DT/DD can be children of a DL'; } form > *:not(fieldset):after { - background: green; + background: #88FF88; content: 'Should you be using a FIELDSET?'; } fieldset *:not(legend):first-child:after { - background: green; + background: #88FF88; content: 'Should your FIELDSET be using a LEGEND?'; } iframe:not([title]):after { - background: green; + background: #88FF88; content: 'IFRAME lacks TITLE attribute.'; } center:after, u:after, font:after { - background: yellow; + background: #FFFF88; content: 'Deprecated tag used.'; } /* These may not be "wrong", but let's bug you anyway. */ map:after { - background: green; + background: #88FF88; content: 'Is MAP appropriate here?'; } b:after, i:after { - background: green; + background: #88FF88; content: 'Should you be using STRONG or EM?'; } blink:after, marquee:after { - background: yellow; + background: #FFFF88; content: 'Should you be using STRONG or EM?'; } @@ -270,7 +279,7 @@ fieldset *:not(legend):first-child, map, b, i { - outline: 5px solid green; + outline: 5px solid #88FF88; } table > tr, @@ -315,5 +324,5 @@ u, font, blink, marquee { - outline: 5px solid yellow; + outline: 5px solid #FFFF88; } \ No newline at end of file From 93d55237f7ccd540df89bf3eb23a6fb0f0f47816 Mon Sep 17 00:00:00 2001 From: Todd Wolfson Date: Sun, 30 Oct 2011 00:22:49 -0700 Subject: [PATCH 02/23] Fixed fieldset legend issue. Green border was appearing on a select box's first option. --- debugCSS.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 0ac164a..7b41a6b 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -74,7 +74,7 @@ ol > *:not(li), ul > *:not(li), dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, -fieldset *:not(legend):first-child:after, +fieldset > *:not(legend):first-child:after, iframe:not([title]):after, center:after, u:after, @@ -224,7 +224,7 @@ form > *:not(fieldset):after { content: 'Should you be using a FIELDSET?'; } -fieldset *:not(legend):first-child:after { +fieldset > *:not(legend):first-child:after { background: #88FF88; content: 'Should your FIELDSET be using a LEGEND?'; } From acea0dc7df63f43a0f7efab8f7728cec870c719f Mon Sep 17 00:00:00 2001 From: Todd Wolfson Date: Sun, 30 Oct 2011 00:46:38 -0700 Subject: [PATCH 03/23] Re: last pull request (I missed a spot) --- debugCSS.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugCSS.css b/debugCSS.css index 0ac164a..5df4553 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -275,7 +275,7 @@ table > tr:first-child:last-child, table > tbody > tr:first-child:last-child, table > tbody:first-child, form > *:not(fieldset), -fieldset *:not(legend):first-child, +fieldset > *:not(legend):first-child, map, b, i { From 40a30dbd46b4bf9845fdb139c28d990272f1df00 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 11 Nov 2011 19:36:11 -0800 Subject: [PATCH 04/23] Added rule for BR tags and fancy image viewer by @skippykawakami --- debugCSS.css | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 0ac164a..21b23d5 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -74,12 +74,14 @@ ol > *:not(li), ul > *:not(li), dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, -fieldset *:not(legend):first-child:after, +fieldset > *:not(legend):first-child:after, iframe:not([title]):after, center:after, u:after, font:after, map:after, +br + *:not(br):before, +br + br + *:before, b:after, i:after, blink:after, @@ -224,7 +226,7 @@ form > *:not(fieldset):after { content: 'Should you be using a FIELDSET?'; } -fieldset *:not(legend):first-child:after { +fieldset > *:not(legend):first-child:after { background: #88FF88; content: 'Should your FIELDSET be using a LEGEND?'; } @@ -247,6 +249,16 @@ map:after { content: 'Is MAP appropriate here?'; } +br + *:not(br):before { + background: #88FF88; + content: 'Is BR appropriate here?'; +} + +br + br + *:before { + background: #88FF88; + content: 'Should you be using a P tag?'; +} + b:after, i:after { background: #88FF88; @@ -275,8 +287,9 @@ table > tr:first-child:last-child, table > tbody > tr:first-child:last-child, table > tbody:first-child, form > *:not(fieldset), -fieldset *:not(legend):first-child, +fieldset > *:not(legend):first-child, map, +br, b, i { outline: 5px solid #88FF88; @@ -325,4 +338,21 @@ font, blink, marquee { outline: 5px solid #FFFF88; +} + +/*********/ +/* EXTRA */ +/*********/ + +/* Stuff that helps in developing / debugging, but don't quite fit anywhere + else. +*/ + +body > img:only-child { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAAOFJJnAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRF/+Pj2tra2dnZ4Z9gVgAAAHxJREFUGBkFwUGKxDAQBDB9shqcuw2T/3TAc5+A95UruZv+IoNqvEWCavLFDB2M5vPgGpyFNOcB80cPJMxgHhLkQ4IxuBorpDA3Y+MazEfC2+gwgnOxHnSogb15F1JcGxmkcBb1AwlVqCIHadZGwt+NGmQhD1lIuB+scOUfnCk3BP0u5SsAAAAASUVORK5CYII=); + border: 50px solid rgba(0, 0, 0, 0.08); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + display: block; + margin: 1em auto; + padding: 0; } \ No newline at end of file From b5aaf197fb178df29d172254924c921eb40dcfc8 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 5 Mar 2012 12:55:49 -0800 Subject: [PATCH 05/23] Block level elements can be children of anchors - but only in HTML5. To be safe, we'll filter by (proper) XHTML. --- debugCSS.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 21b23d5..8956b1a 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -62,9 +62,9 @@ h3 div:after, h4 div:after, h5 div:after, h6 div:after, -a div:after, span div:after, -html[xmlns] a h1:after, /* Try to select only in XHTML documents (thanks, Thierry). */ +html[xmlns] a div:after, /* Try to select only in XHTML documents (thanks, Thierry). */ +html[xmlns] a h1:after, html[xmlns] a h2:after, html[xmlns] a h3:after, html[xmlns] a h4:after, @@ -198,8 +198,8 @@ h3 div:after, h4 div:after, h5 div:after, h6 div:after, -a div:after, span div:after, +html[xmlns] a div:after, html[xmlns] a h1:after, html[xmlns] a h2:after, html[xmlns] a h3:after, @@ -320,8 +320,8 @@ h3 div, h4 div, h5 div, h6 div, -a div, span div, +html[xmlns] a div, html[xmlns] a h1, html[xmlns] a h2, html[xmlns] a h3, From 815452c162806b987ed9f328f4c6af2f790839d9 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 5 Dec 2012 10:24:40 -0800 Subject: [PATCH 06/23] Minor tweaks Fixed a minor bug in checking non-LI elements in UL/OL (content was overwritten instead of applying content to :after pseudo-element). Shortened table non-TR selector. Clarified that not using SCOPE for TH is ok if you're using ID and HEADERS instead. --- debugCSS.css | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 8956b1a..72d7217 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -37,8 +37,8 @@ table th:not([scope]):after, table thead td:after, table > tbody:first-child:after, table > tbody + tfoot:after, -table > tr:first-child:last-child:after, -table > tbody > tr:first-child:last-child:after, +table > tr:only-child:after, +table > tbody > tr:only-child:after, table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption):after, table[align]:after, table[bgcolor]:after, @@ -70,8 +70,8 @@ html[xmlns] a h3:after, html[xmlns] a h4:after, html[xmlns] a h5:after, html[xmlns] a h6:after, -ol > *:not(li), -ul > *:not(li), +ol > *:not(li):after, +ul > *:not(li):after, dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, fieldset > *:not(legend):first-child:after, @@ -119,7 +119,7 @@ table > tr:after { table th:not([scope]):after { background: #88FF88; - content: 'Should TH have a SCOPE attribute (ROW or COL)?.'; + content: 'Should TH have a SCOPE attribute (ROW or COL)? OK if using ID and HEADERS.'; } table thead td:after { @@ -137,8 +137,8 @@ table > tbody + tfoot:after { content: 'TBODY should come after TFOOT.'; } -table > tr:first-child:last-child:after, -table > tbody > tr:first-child:last-child:after { +table > tr:only-child:after, +table > tbody > tr:only-child:after { background: #88FF88; content: 'Only one TR in TABLE. Are you using it for layout?'; } From 8948f46fe7cb9a1fe96140ef1d471160561e56d0 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 14 Mar 2013 11:53:29 -0700 Subject: [PATCH 07/23] Added check for img tags without src attributes If an image tag is defined without a src attribute, it can cause some browsers to make requests to "/", which can have dramatic performance implications. Put severity to RED (the only set of rules currently at this high state) because of the big performance ding, difficulty in quickly finding the issue and how easy it is for developers to accidentally pass a null string when building markup. --- debugCSS.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debugCSS.css b/debugCSS.css index 72d7217..b50a788 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -47,6 +47,9 @@ table[cellpadding]:after, table[cellspacing]:after, table[width]:after, img:not([alt]):after, +img:not([src]):after, +img[src=""]:after, +img[src="#"]:after, a:not([href]):after, a[href="#"]:after, a[href*=javascript\:]:after, @@ -163,6 +166,13 @@ img:not([alt]):after { content: 'Image does not have an ALT attribute.'; } +img:not([src]):after, +img[src=""]:after, +img[src="#"]:after { + background: #FF8888; + content: 'IMG without proper SRC attribute. Serious implications for some browsers.'; +} + a[href="#"]:after, a:not([href]):after { background: #FFFF88; @@ -279,6 +289,11 @@ marquee:after { element so it's easy to spot. Use outline instead of border to avoid messing with the document flow. */ +img:not([src]), +img[src=""], +img[src="#"] { + outline: 5px solid #FF8888; +} table:not([summary]), table th:not([scope]), From 1b763ec421003390e71fc59ae7b3636915d5c7f5 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 19 Sep 2013 17:44:42 -0700 Subject: [PATCH 08/23] Additional common inline styles, added check for class names that start with numbers Height, Width, Border (three common inline styles) now have a check. These are not invalid for transitional doctypes, but probably worth noting, regardless. Also added a check for any CSS class or ID that starts with a number. --- debugCSS.css | 110 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 18 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index b50a788..4b2eb3d 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -45,7 +45,9 @@ table[bgcolor]:after, table[border]:after, table[cellpadding]:after, table[cellspacing]:after, -table[width]:after, +*[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ +*[height]:after, +*[border]:after, img:not([alt]):after, img:not([src]):after, img[src=""]:after, @@ -79,6 +81,26 @@ dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, fieldset > *:not(legend):first-child:after, iframe:not([title]):after, +*[class^="1"]:after, +*[class^="2"]:after, +*[class^="3"]:after, +*[class^="4"]:after, +*[class^="5"]:after, +*[class^="6"]:after, +*[class^="7"]:after, +*[class^="8"]:after, +*[class^="9"]:after, +*[class^="0"]:after, +*[id^="1"]:after, +*[id^="2"]:after, +*[id^="3"]:after, +*[id^="4"]:after, +*[id^="5"]:after, +*[id^="6"]:after, +*[id^="7"]:after, +*[id^="8"]:after, +*[id^="9"]:after, +*[id^="0"]:after, center:after, u:after, font:after, @@ -156,7 +178,9 @@ table[bgcolor]:after, table[border]:after, table[cellpadding]:after, table[cellspacing]:after, -table[width]:after { +*[width]:after, +*[height]:after, +*[border]:after { background: #FFFF88; content: 'Element has inline style.'; } @@ -246,6 +270,34 @@ iframe:not([title]):after { content: 'IFRAME lacks TITLE attribute.'; } +*[class^="1"]:after, +*[class^="2"]:after, +*[class^="3"]:after, +*[class^="4"]:after, +*[class^="5"]:after, +*[class^="6"]:after, +*[class^="7"]:after, +*[class^="8"]:after, +*[class^="9"]:after, +*[class^="0"]:after { + background: #FFFF88; + content: 'Class name cannot start with number.'; +} + +*[id^="1"]:after, +*[id^="2"]:after, +*[id^="3"]:after, +*[id^="4"]:after, +*[id^="5"]:after, +*[id^="6"]:after, +*[id^="7"]:after, +*[id^="8"]:after, +*[id^="9"]:after, +*[id^="0"]:after { + background: #FFFF88; + content: 'ID cannot start with number.'; +} + center:after, u:after, font:after { @@ -295,21 +347,6 @@ img[src="#"] { outline: 5px solid #FF8888; } -table:not([summary]), -table th:not([scope]), -table thead td, -table > tr:first-child:last-child, -table > tbody > tr:first-child:last-child, -table > tbody:first-child, -form > *:not(fieldset), -fieldset > *:not(legend):first-child, -map, -br, -b, -i { - outline: 5px solid #88FF88; -} - table > tr, table > tbody + tfoot, table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption), @@ -318,7 +355,9 @@ table[bgcolor], table[border], table[cellpadding], table[cellspacing], -table[width], +*[width], +*[height], +*[border], img:not([alt]), a:not([href]), a[href="#"], @@ -347,6 +386,26 @@ ol > *:not(li), ul > *:not(li), dl > *:not(dt):not(dd), iframe:not([title]), +*[class^="1"], +*[class^="2"], +*[class^="3"], +*[class^="4"], +*[class^="5"], +*[class^="6"], +*[class^="7"], +*[class^="8"], +*[class^="9"], +*[class^="0"], +*[id^="1"], +*[id^="2"], +*[id^="3"], +*[id^="4"], +*[id^="5"], +*[id^="6"], +*[id^="7"], +*[id^="8"], +*[id^="9"], +*[id^="0"], center, u, font, @@ -355,6 +414,21 @@ marquee { outline: 5px solid #FFFF88; } +table:not([summary]), +table th:not([scope]), +table thead td, +table > tr:first-child:last-child, +table > tbody > tr:first-child:last-child, +table > tbody:first-child, +form > *:not(fieldset), +fieldset > *:not(legend):first-child, +map, +br, +b, +i { + outline: 5px solid #88FF88; +} + /*********/ /* EXTRA */ /*********/ From 8db62dbbb01a61ab1cc043ebe132818a46922cbb Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 8 Nov 2013 20:53:29 -0800 Subject: [PATCH 09/23] Focus on validating proper classnames and IDs Did you know that you can use a space in a class name - as long as it's escaped? They're invalid, but supported in browsers. You can also use a "." and a "#". There's a long list of illegal characters you shouldn't use and now DebugCSS filters for the worst offenders. --- debugCSS.css | 218 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 203 insertions(+), 15 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 4b2eb3d..94f01ce 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -81,6 +81,16 @@ dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, fieldset > *:not(legend):first-child:after, iframe:not([title]):after, +center:after, +u:after, +font:after, +map:after, +br + *:not(br):before, +br + br + *:before, +b:after, +i:after, +blink:after, +marquee:after, *[class^="1"]:after, *[class^="2"]:after, *[class^="3"]:after, @@ -101,16 +111,64 @@ iframe:not([title]):after, *[id^="8"]:after, *[id^="9"]:after, *[id^="0"]:after, -center:after, -u:after, -font:after, -map:after, -br + *:not(br):before, -br + br + *:before, -b:after, -i:after, -blink:after, -marquee:after { +*[class*=\\]:after, +*[class*=\.]:after, +*[class*=\#]:after, +*[class*=\~]:after, +*[class*=\!]:after, +*[class*=\@]:after, +*[class*=\$]:after, +*[class*=\%]:after, +*[class*=\^]:after, +*[class*=\&]:after, +*[class*=\*]:after, +*[class*=\(]:after, +*[class*=\)]:after, +*[class*=\=]:after, +*[class*=\,]:after, +*[class*=\/]:after, +*[class*=\']:after, +*[class*=\;]:after, +*[class*=\:]:after, +*[class*=\"]:after, +*[class*=\?]:after, +*[class*=\>]:after, +*[class*=\<]:after, +*[class*=\[]:after, +*[class*=\]]:after, +*[class*=\{]:after, +*[class*=\}]:after, +*[class*=\|]:after, +*[class*=\`]:after, +*[id*=\\]:after, +*[id*=\.]:after, +*[id*=\#]:after, +*[id*=\~]:after, +*[id*=\!]:after, +*[id*=\@]:after, +*[id*=\$]:after, +*[id*=\%]:after, +*[id*=\^]:after, +*[id*=\&]:after, +*[id*=\*]:after, +*[id*=\(]:after, +*[id*=\)]:after, +*[id*=\=]:after, +*[id*=\,]:after, +*[id*=\/]:after, +*[id*=\']:after, +*[id*=\;]:after, +*[id*=\:]:after, +*[id*=\"]:after, +*[id*=\?]:after, +*[id*=\>]:after, +*[id*=\<]:after, +*[id*=\[]:after, +*[id*=\]]:after, +*[id*=\{]:after, +*[id*=\}]:after, +*[id*=\|]:after, +*[id*=\`]:after, { border: 1px solid #000; color: #000; display: block; @@ -270,6 +328,13 @@ iframe:not([title]):after { content: 'IFRAME lacks TITLE attribute.'; } +center:after, +u:after, +font:after { + background: #FFFF88; + content: 'Deprecated tag used.'; +} + *[class^="1"]:after, *[class^="2"]:after, *[class^="3"]:after, @@ -298,11 +363,78 @@ iframe:not([title]):after { content: 'ID cannot start with number.'; } -center:after, -u:after, -font:after { +*[class*=\\]:after, +*[class*=\.]:after, +*[class*=\#]:after { + background: #FF8888; + content: 'Classname has an ambiguous character.'; +} + +*[id*=\\]:after, +*[id*=\.]:after, +*[id*=\#]:after { + background: #FF8888; + content: 'ID has an ambiguous character.'; +} + +*[class*=\~]:after, +*[class*=\!]:after, +*[class*=\@]:after, +*[class*=\$]:after, +*[class*=\%]:after, +*[class*=\^]:after, +*[class*=\&]:after, +*[class*=\*]:after, +*[class*=\(]:after, +*[class*=\)]:after, +*[class*=\=]:after, +*[class*=\,]:after, +*[class*=\/]:after, +*[class*=\']:after, +*[class*=\;]:after, +*[class*=\:]:after, +*[class*=\"]:after, +*[class*=\?]:after, +*[class*=\>]:after, +*[class*=\<]:after, +*[class*=\[]:after, +*[class*=\]]:after, +*[class*=\{]:after, +*[class*=\}]:after, +*[class*=\|]:after, +*[class*=\`]:after { background: #FFFF88; - content: 'Deprecated tag used.'; + content: 'Class has an ambiguous character.'; +} + +*[id*=\~]:after, +*[id*=\!]:after, +*[id*=\@]:after, +*[id*=\$]:after, +*[id*=\%]:after, +*[id*=\^]:after, +*[id*=\&]:after, +*[id*=\*]:after, +*[id*=\(]:after, +*[id*=\)]:after, +*[id*=\=]:after, +*[id*=\,]:after, +*[id*=\/]:after, +*[id*=\']:after, +*[id*=\;]:after, +*[id*=\:]:after, +*[id*=\"]:after, +*[id*=\?]:after, +*[id*=\>]:after, +*[id*=\<]:after, +*[id*=\[]:after, +*[id*=\]]:after, +*[id*=\{]:after, +*[id*=\}]:after, +*[id*=\|]:after, +*[id*=\`]:after { + background: #FFFF88; + content: 'ID has an ambiguous character.'; } /* These may not be "wrong", but let's bug you anyway. */ @@ -343,7 +475,13 @@ marquee:after { */ img:not([src]), img[src=""], -img[src="#"] { +img[src="#"], +*[class*=\\], +*[class*=\.], +*[class*=\#], +*[id*=\\], +*[id*=\.], +*[id*=\#] { outline: 5px solid #FF8888; } @@ -406,6 +544,56 @@ iframe:not([title]), *[id^="8"], *[id^="9"], *[id^="0"], +*[class*=\~], +*[class*=\!], +*[class*=\@], +*[class*=\$], +*[class*=\%], +*[class*=\^], +*[class*=\&], +*[class*=\*], +*[class*=\(], +*[class*=\)], +*[class*=\=], +*[class*=\,], +*[class*=\/], +*[class*=\'], +*[class*=\;], +*[class*=\:], +*[class*=\?], +*[class*=\>], +*[class*=\<], +*[class*=\[], +*[class*=\]], +*[class*=\{], +*[class*=\}], +*[class*=\|], +*[class*=\`], +*[id*=\~], +*[id*=\!], +*[id*=\@], +*[id*=\$], +*[id*=\%], +*[id*=\^], +*[id*=\&], +*[id*=\*], +*[id*=\(], +*[id*=\)], +*[id*=\=], +*[id*=\,], +*[id*=\/], +*[id*=\'], +*[id*=\;], +*[id*=\:], +*[id*=\?], +*[id*=\>], +*[id*=\<], +*[id*=\[], +*[id*=\]], +*[id*=\{], +*[id*=\}], +*[id*=\|], +*[id*=\`], center, u, font, From 7f3908f7d5324e61923b724b722f770424b0ebb0 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 11 Nov 2013 11:01:08 -0800 Subject: [PATCH 10/23] Fix verbiage, typo Typo left warnings styled funky. Change verbiage for illegal chars that are just wrong and not ambiguous. --- debugCSS.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 94f01ce..65af4d2 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -168,7 +168,7 @@ marquee:after, *[id*=\{]:after, *[id*=\}]:after, *[id*=\|]:after, -*[id*=\`]:after, { +*[id*=\`]:after { border: 1px solid #000; color: #000; display: block; @@ -404,7 +404,7 @@ font:after { *[class*=\|]:after, *[class*=\`]:after { background: #FFFF88; - content: 'Class has an ambiguous character.'; + content: 'Class has an illegal character.'; } *[id*=\~]:after, @@ -434,7 +434,7 @@ font:after { *[id*=\|]:after, *[id*=\`]:after { background: #FFFF88; - content: 'ID has an ambiguous character.'; + content: 'ID has an illegal character.'; } /* These may not be "wrong", but let's bug you anyway. */ From 72c3c15587c9b4d3e0d5a6c46279a166e3a72336 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 15 Nov 2013 13:55:54 -0800 Subject: [PATCH 11/23] Add checks for potentially nonsemantic class / id names, additional table checks. Tries to check for classnames and IDs that are potentially non-semantic. Presents the actual classname / ID in the notice so you can quickly see if it's a false alarm. SOC is touchy, but this is probably worth at least saying "is this actually what you want?" Added more table related checks for colgroups, captions and order of elements. --- debugCSS.css | 312 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 288 insertions(+), 24 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 65af4d2..e30c7a6 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -35,11 +35,21 @@ table:not([summary]):after, table > tr:after, table th:not([scope]):after, table thead td:after, +table > colgroup ~ caption:after, +table > thead ~ colgroup:after, +table > tfoot ~ colgroup:after, +table > tbody ~ colgroup:after, +table > thead ~ caption:after, +table > tfoot ~ caption:after, +table > tbody ~ caption:after, table > tbody:first-child:after, -table > tbody + tfoot:after, +table > tfoot ~ thead:after, +table > tbody ~ tfoot:after, +table > tbody ~ thead:after, table > tr:only-child:after, table > tbody > tr:only-child:after, table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption):after, +colgroup *:not(col):after, table[align]:after, table[bgcolor]:after, table[border]:after, @@ -48,6 +58,10 @@ table[cellspacing]:after, *[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ *[height]:after, *[border]:after, +div:empty:after, +span:empty:after, +p:empty:after, +a a:after, img:not([alt]):after, img:not([src]):after, img[src=""]:after, @@ -111,6 +125,66 @@ marquee:after, *[id^="8"]:after, *[id^="9"]:after, *[id^="0"]:after, +*[class*=left]:after, +*[class*=right]:after, +*[class*=top]:after, +*[class*=bottom]:after, +*[class*=center]:after, +*[class*=clear]:after, +*[class*=float]:after, +*[class*=large]:after, +*[class*=small]:after, +*[class*=red]:after, +*[class*=blue]:after, +*[class*=green]:after, +*[class*=yellow]:after, +*[class*=white]:after, +*[class*=black]:after, +*[class*=Left]:after, +*[class*=Right]:after, +*[class*=Top]:after, +*[class*=Bottom]:after, +*[class*=Center]:after, +*[class*=Clear]:after, +*[class*=Float]:after, +*[class*=Large]:after, +*[class*=Small]:after, +*[class*=Red]:after, +*[class*=Blue]:after, +*[class*=Green]:after, +*[class*=Yellow]:after, +*[class*=White]:after, +*[class*=Black]:after, +*[id*=left]:after, +*[id*=right]:after, +*[id*=top]:after, +*[id*=bottom]:after, +*[id*=center]:after, +*[id*=clear]:after, +*[id*=float]:after, +*[id*=large]:after, +*[id*=small]:after, +*[id*=red]:after, +*[id*=blue]:after, +*[id*=green]:after, +*[id*=yellow]:after, +*[id*=white]:after, +*[id*=black]:after, +*[id*=Left]:after, +*[id*=Right]:after, +*[id*=Top]:after, +*[id*=Bottom]:after, +*[id*=Center]:after, +*[id*=Clear]:after, +*[id*=Float]:after, +*[id*=Large]:after, +*[id*=Small]:after, +*[id*=Red]:after, +*[id*=Blue]:after, +*[id*=Green]:after, +*[id*=Yellow]:after, +*[id*=White]:after, +*[id*=Black]:after, *[class*=\\]:after, *[class*=\.]:after, *[class*=\#]:after, @@ -197,17 +271,36 @@ table:not([summary]):after { table > tr:after { background: #FFFF88; - content: 'TABLE does not have a TBODY.'; + content: 'TABLE does not have a TBODY'; } table th:not([scope]):after { background: #88FF88; - content: 'Should TH have a SCOPE attribute (ROW or COL)? OK if using ID and HEADERS.'; + content: 'Should TH have a SCOPE attribute (ROW or COL)? OK if using ID and HEADERS'; } table thead td:after { background: #88FF88; - content: 'Cells in THEAD should be TH.'; + content: 'Cells in THEAD should be TH'; +} + +table > colgroup ~ caption:after { + background: #FFFF88; + content: 'CAPTION must come before COLGROUP'; +} + +table > thead ~ colgroup:after, +table > tfoot ~ colgroup:after, +table > tbody ~ colgroup:after { + background: #FFFF88; + content: 'COLGROUP must come before THEAD, TFOOT and TBODY'; +} + +table > thead ~ caption:after, +table > tfoot ~ caption:after, +table > tbody ~ caption:after { + background: #FFFF88; + content: 'CAPTION must come before THEAD, TFOOT and TBODY'; } table > tbody:first-child:after { @@ -215,9 +308,19 @@ table > tbody:first-child:after { content: 'Do you need a THEAD or TFOOT?'; } -table > tbody + tfoot:after { +table > tfoot ~ thead:after { + background: #FFFF88; + content: 'TFOOT should come after THEAD'; +} + +table > tbody ~ tfoot:after { + background: #FFFF88; + content: 'TBODY should come after TFOOT'; +} + +table > tbody ~ thead:after { background: #FFFF88; - content: 'TBODY should come after TFOOT.'; + content: 'TBODY should come after THEAD'; } table > tr:only-child:after, @@ -231,6 +334,11 @@ table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption):af content: 'Only THEAD/TFOOT/TBODY/COLGROUP/CAPTION/TR can be children of a TABLE'; } +colgroup *:not(col):after { + background: #FFFF88; + content: 'Only COLs can be children of COLGROUP'; +} + table[align]:after, table[bgcolor]:after, table[border]:after, @@ -240,25 +348,37 @@ table[cellspacing]:after, *[height]:after, *[border]:after { background: #FFFF88; - content: 'Element has inline style.'; + content: 'Element has inline style'; +} + +div:empty:after, +span:empty:after, +p:empty:after { + background: #FFFF88; + content: 'Element has no content. Is this necessary?'; +} + +a a:after { + background: #FF8888; + content: 'A tag within another A tag - this looks like a bug'; } img:not([alt]):after { background: #FFFF88; - content: 'Image does not have an ALT attribute.'; + content: 'Image does not have an ALT attribute'; } img:not([src]):after, img[src=""]:after, img[src="#"]:after { background: #FF8888; - content: 'IMG without proper SRC attribute. Serious implications for some browsers.'; + content: 'IMG without proper SRC attribute. Serious implications for some browsers'; } a[href="#"]:after, a:not([href]):after { background: #FFFF88; - content: 'Anchor tag is # or does not exist - does not degrade gracefully.'; + content: 'Anchor tag is # or does not exist - does not degrade gracefully'; } a[href*=javascript\:]:after, @@ -266,7 +386,7 @@ a[onclick]:after, a[onmouseover]:after, a[onmouseout]:after { background: #FFFF88; - content: 'Inline JS on anchor.'; + content: 'Inline JS on anchor'; } label:not([for]):after { @@ -276,12 +396,12 @@ label:not([for]):after { nav:not([role]):after { background: #FFFF88; - content: 'NAV element should have a ROLE attribute.'; + content: 'NAV element should have a ROLE attribute'; } div[role="img"]:not([aria-label]):after { background: #FFFF88; - content: 'DIV used as image should have ARIA-LABEL.'; + content: 'DIV used as image should have ARIA-LABEL'; } h1 div:after, @@ -299,7 +419,7 @@ html[xmlns] a h4:after, html[xmlns] a h5:after, html[xmlns] a h6:after { background: #FFFF88; - content: 'Block level element within inline element.'; + content: 'Block level element within inline element'; } ol > *:not(li):after, @@ -325,14 +445,14 @@ fieldset > *:not(legend):first-child:after { iframe:not([title]):after { background: #88FF88; - content: 'IFRAME lacks TITLE attribute.'; + content: 'IFRAME lacks TITLE attribute'; } center:after, u:after, font:after { background: #FFFF88; - content: 'Deprecated tag used.'; + content: 'Deprecated tag used'; } *[class^="1"]:after, @@ -346,7 +466,7 @@ font:after { *[class^="9"]:after, *[class^="0"]:after { background: #FFFF88; - content: 'Class name cannot start with number.'; + content: 'Class name cannot start with number'; } *[id^="1"]:after, @@ -360,21 +480,91 @@ font:after { *[id^="9"]:after, *[id^="0"]:after { background: #FFFF88; - content: 'ID cannot start with number.'; + content: 'ID cannot start with number'; +} + +*[class*=left]:after, +*[class*=right]:after, +*[class*=top]:after, +*[class*=bottom]:after, +*[class*=center]:after, +*[class*=clear]:after, +*[class*=float]:after, +*[class*=large]:after, +*[class*=small]:after, +*[class*=red]:after, +*[class*=blue]:after, +*[class*=green]:after, +*[class*=yellow]:after, +*[class*=white]:after, +*[class*=black]:after, +*[class*=Left]:after, +*[class*=Right]:after, +*[class*=Top]:after, +*[class*=Bottom]:after, +*[class*=Center]:after, +*[class*=Clear]:after, +*[class*=Float]:after, +*[class*=Large]:after, +*[class*=Small]:after, +*[class*=Red]:after, +*[class*=Blue]:after, +*[class*=Green]:after, +*[class*=Yellow]:after, +*[class*=White]:after, +*[class*=Black]:after { + background: #88FF88; + /* I know that these aren't necessarily bad, but probably worth highlighting */ + content: attr(class) ' has implied style meaning - should you be naming it differently?' +} + +*[id*=left]:after, +*[id*=right]:after, +*[id*=top]:after, +*[id*=bottom]:after, +*[id*=center]:after, +*[id*=clear]:after, +*[id*=float]:after, +*[id*=large]:after, +*[id*=small]:after, +*[id*=red]:after, +*[id*=blue]:after, +*[id*=green]:after, +*[id*=yellow]:after, +*[id*=white]:after, +*[id*=black]:after, +*[id*=Left]:after, +*[id*=Right]:after, +*[id*=Top]:after, +*[id*=Bottom]:after, +*[id*=Center]:after, +*[id*=Clear]:after, +*[id*=Float]:after, +*[id*=Large]:after, +*[id*=Small]:after, +*[id*=Red]:after, +*[id*=Blue]:after, +*[id*=Green]:after, +*[id*=Yellow]:after, +*[id*=White]:after, +*[id*=Black]:after { + background: #88FF88; + /* I know that these aren't necessarily bad, but probably worth highlighting */ + content: attr(id) ' has implied style meaning - should you be naming it differently?' } *[class*=\\]:after, *[class*=\.]:after, *[class*=\#]:after { background: #FF8888; - content: 'Classname has an ambiguous character.'; + content: 'Classname has an ambiguous character'; } *[id*=\\]:after, *[id*=\.]:after, *[id*=\#]:after { background: #FF8888; - content: 'ID has an ambiguous character.'; + content: 'ID has an ambiguous character'; } *[class*=\~]:after, @@ -404,7 +594,7 @@ font:after { *[class*=\|]:after, *[class*=\`]:after { background: #FFFF88; - content: 'Class has an illegal character.'; + content: 'Class has an illegal character'; } *[id*=\~]:after, @@ -434,7 +624,7 @@ font:after { *[id*=\|]:after, *[id*=\`]:after { background: #FFFF88; - content: 'ID has an illegal character.'; + content: 'ID has an illegal character'; } /* These may not be "wrong", but let's bug you anyway. */ @@ -473,6 +663,7 @@ marquee:after { element so it's easy to spot. Use outline instead of border to avoid messing with the document flow. */ +a a, img:not([src]), img[src=""], img[src="#"], @@ -486,7 +677,17 @@ img[src="#"], } table > tr, -table > tbody + tfoot, +table > colgroup ~ caption, +table > thead ~ colgroup, +table > tfoot ~ colgroup, +table > tbody ~ colgroup, +table > thead ~ caption, +table > tfoot ~ caption, +table > tbody ~ caption, +table > tfoot ~ thead, +table > tbody ~ tfoot, +table > tbody ~ thead, +colgroup *:not(col), table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption), table[align], table[bgcolor], @@ -496,6 +697,9 @@ table[cellspacing], *[width], *[height], *[border], +div:empty:after, +span:empty, +p:empty, img:not([alt]), a:not([href]), a[href="#"], @@ -613,7 +817,67 @@ fieldset > *:not(legend):first-child, map, br, b, -i { +i, +*[class*=left], +*[class*=right], +*[class*=top], +*[class*=bottom], +*[class*=center], +*[class*=clear], +*[class*=float], +*[class*=large], +*[class*=small], +*[class*=red], +*[class*=blue], +*[class*=green], +*[class*=yellow], +*[class*=white], +*[class*=black], +*[class*=Left], +*[class*=Right], +*[class*=Top], +*[class*=Bottom], +*[class*=Center], +*[class*=Clear], +*[class*=Float], +*[class*=Large], +*[class*=Small], +*[class*=Red], +*[class*=Blue], +*[class*=Green], +*[class*=Yellow], +*[class*=White], +*[class*=Black], +*[id*=left], +*[id*=right], +*[id*=top], +*[id*=bottom], +*[id*=center], +*[id*=clear], +*[id*=float], +*[id*=large], +*[id*=small], +*[id*=red], +*[id*=blue], +*[id*=green], +*[id*=yellow], +*[id*=white], +*[id*=black], +*[id*=Left], +*[id*=Right], +*[id*=Top], +*[id*=Bottom], +*[id*=Center], +*[id*=Clear], +*[id*=Float], +*[id*=Large], +*[id*=Small], +*[id*=Red], +*[id*=Blue], +*[id*=Green], +*[id*=Yellow], +*[id*=White], +*[id*=Black] { outline: 5px solid #88FF88; } From f1b61f32451b7a084701cf193ac30db0cd8bae06 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 15 Nov 2013 16:09:25 -0800 Subject: [PATCH 12/23] Remove red / top - too many false positives --- debugCSS.css | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index e30c7a6..b5a8197 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -127,14 +127,12 @@ marquee:after, *[id^="0"]:after, *[class*=left]:after, *[class*=right]:after, -*[class*=top]:after, *[class*=bottom]:after, *[class*=center]:after, *[class*=clear]:after, *[class*=float]:after, *[class*=large]:after, *[class*=small]:after, -*[class*=red]:after, *[class*=blue]:after, *[class*=green]:after, *[class*=yellow]:after, @@ -142,14 +140,12 @@ marquee:after, *[class*=black]:after, *[class*=Left]:after, *[class*=Right]:after, -*[class*=Top]:after, *[class*=Bottom]:after, *[class*=Center]:after, *[class*=Clear]:after, *[class*=Float]:after, *[class*=Large]:after, *[class*=Small]:after, -*[class*=Red]:after, *[class*=Blue]:after, *[class*=Green]:after, *[class*=Yellow]:after, @@ -157,14 +153,12 @@ marquee:after, *[class*=Black]:after, *[id*=left]:after, *[id*=right]:after, -*[id*=top]:after, *[id*=bottom]:after, *[id*=center]:after, *[id*=clear]:after, *[id*=float]:after, *[id*=large]:after, *[id*=small]:after, -*[id*=red]:after, *[id*=blue]:after, *[id*=green]:after, *[id*=yellow]:after, @@ -172,14 +166,12 @@ marquee:after, *[id*=black]:after, *[id*=Left]:after, *[id*=Right]:after, -*[id*=Top]:after, *[id*=Bottom]:after, *[id*=Center]:after, *[id*=Clear]:after, *[id*=Float]:after, *[id*=Large]:after, *[id*=Small]:after, -*[id*=Red]:after, *[id*=Blue]:after, *[id*=Green]:after, *[id*=Yellow]:after, @@ -485,14 +477,12 @@ font:after { *[class*=left]:after, *[class*=right]:after, -*[class*=top]:after, *[class*=bottom]:after, *[class*=center]:after, *[class*=clear]:after, *[class*=float]:after, *[class*=large]:after, *[class*=small]:after, -*[class*=red]:after, *[class*=blue]:after, *[class*=green]:after, *[class*=yellow]:after, @@ -500,14 +490,12 @@ font:after { *[class*=black]:after, *[class*=Left]:after, *[class*=Right]:after, -*[class*=Top]:after, *[class*=Bottom]:after, *[class*=Center]:after, *[class*=Clear]:after, *[class*=Float]:after, *[class*=Large]:after, *[class*=Small]:after, -*[class*=Red]:after, *[class*=Blue]:after, *[class*=Green]:after, *[class*=Yellow]:after, @@ -515,19 +503,17 @@ font:after { *[class*=Black]:after { background: #88FF88; /* I know that these aren't necessarily bad, but probably worth highlighting */ - content: attr(class) ' has implied style meaning - should you be naming it differently?' + content: attr(class) ' has implied style meaning - should you be naming it differently?'; } *[id*=left]:after, *[id*=right]:after, -*[id*=top]:after, *[id*=bottom]:after, *[id*=center]:after, *[id*=clear]:after, *[id*=float]:after, *[id*=large]:after, *[id*=small]:after, -*[id*=red]:after, *[id*=blue]:after, *[id*=green]:after, *[id*=yellow]:after, @@ -535,14 +521,12 @@ font:after { *[id*=black]:after, *[id*=Left]:after, *[id*=Right]:after, -*[id*=Top]:after, *[id*=Bottom]:after, *[id*=Center]:after, *[id*=Clear]:after, *[id*=Float]:after, *[id*=Large]:after, *[id*=Small]:after, -*[id*=Red]:after, *[id*=Blue]:after, *[id*=Green]:after, *[id*=Yellow]:after, @@ -550,7 +534,7 @@ font:after { *[id*=Black]:after { background: #88FF88; /* I know that these aren't necessarily bad, but probably worth highlighting */ - content: attr(id) ' has implied style meaning - should you be naming it differently?' + content: attr(id) ' has implied style meaning - should you be naming it differently?'; } *[class*=\\]:after, @@ -820,14 +804,12 @@ b, i, *[class*=left], *[class*=right], -*[class*=top], *[class*=bottom], *[class*=center], *[class*=clear], *[class*=float], *[class*=large], *[class*=small], -*[class*=red], *[class*=blue], *[class*=green], *[class*=yellow], @@ -835,14 +817,12 @@ i, *[class*=black], *[class*=Left], *[class*=Right], -*[class*=Top], *[class*=Bottom], *[class*=Center], *[class*=Clear], *[class*=Float], *[class*=Large], *[class*=Small], -*[class*=Red], *[class*=Blue], *[class*=Green], *[class*=Yellow], @@ -850,14 +830,12 @@ i, *[class*=Black], *[id*=left], *[id*=right], -*[id*=top], *[id*=bottom], *[id*=center], *[id*=clear], *[id*=float], *[id*=large], *[id*=small], -*[id*=red], *[id*=blue], *[id*=green], *[id*=yellow], @@ -865,14 +843,12 @@ i, *[id*=black], *[id*=Left], *[id*=Right], -*[id*=Top], *[id*=Bottom], *[id*=Center], *[id*=Clear], *[id*=Float], *[id*=Large], *[id*=Small], -*[id*=Red], *[id*=Blue], *[id*=Green], *[id*=Yellow], From b0e15f0cfb805170815d4695645dea9effa697c2 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 21 Nov 2013 10:38:00 -0800 Subject: [PATCH 13/23] False positives for "right" check Check for occurrence of "opyright" (in case C is capital or lower case) to remove false positives for copyright elements (which sound like a good namespace). --- debugCSS.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index b5a8197..c5b050e 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -126,7 +126,7 @@ marquee:after, *[id^="9"]:after, *[id^="0"]:after, *[class*=left]:after, -*[class*=right]:after, +*[class*=right]:not([class*=opyright]):after, *[class*=bottom]:after, *[class*=center]:after, *[class*=clear]:after, @@ -152,7 +152,7 @@ marquee:after, *[class*=White]:after, *[class*=Black]:after, *[id*=left]:after, -*[id*=right]:after, +*[id*=right]:not([id*=opyright]):after, *[id*=bottom]:after, *[id*=center]:after, *[id*=clear]:after, @@ -476,7 +476,7 @@ font:after { } *[class*=left]:after, -*[class*=right]:after, +*[class*=right]:not([class*=opyright]):after, *[class*=bottom]:after, *[class*=center]:after, *[class*=clear]:after, @@ -507,7 +507,7 @@ font:after { } *[id*=left]:after, -*[id*=right]:after, +*[id*=right]:not([id*=opyright]):after, *[id*=bottom]:after, *[id*=center]:after, *[id*=clear]:after, @@ -803,7 +803,7 @@ br, b, i, *[class*=left], -*[class*=right], +*[class*=right]:not([class*=opyright]), *[class*=bottom], *[class*=center], *[class*=clear], @@ -829,7 +829,7 @@ i, *[class*=White], *[class*=Black], *[id*=left], -*[id*=right], +*[id*=right]:not([id*=opyright]), *[id*=bottom], *[id*=center], *[id*=clear], From 6b7c15ccb5dac65ef32617cddbca8c2ef5715772 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 29 Nov 2013 16:22:40 -0800 Subject: [PATCH 14/23] Add check for more common elements without content --- debugCSS.css | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/debugCSS.css b/debugCSS.css index c5b050e..065dd11 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -61,6 +61,13 @@ table[cellspacing]:after, div:empty:after, span:empty:after, p:empty:after, +ul:empty:after, +ol:empty:after, +dl:empty:after, +li:empty:after, +dt:empty:after, +dd:empty:after, +a:empty:after, a a:after, img:not([alt]):after, img:not([src]):after, @@ -345,7 +352,14 @@ table[cellspacing]:after, div:empty:after, span:empty:after, -p:empty:after { +p:empty:after, +ul:empty:after, +ol:empty:after, +dl:empty:after, +li:empty:after, +dt:empty:after, +dd:empty:after, +a:empty:after { background: #FFFF88; content: 'Element has no content. Is this necessary?'; } @@ -684,6 +698,13 @@ table[cellspacing], div:empty:after, span:empty, p:empty, +ul:empty, +ol:empty, +dl:empty, +li:empty, +dt:empty, +dd:empty, +a:empty, img:not([alt]), a:not([href]), a[href="#"], From 69e9d9203a596b42fd8f47691802769ff0afd1fb Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 21 Jan 2014 22:12:04 -0800 Subject: [PATCH 15/23] Try to display error notes for void elements Void elements (input, img, br) cannot show CSS content. Instead of relying on a user inspecting an element to find the associated error code hidden in a developer tool - try to surface that message with the next available non-void element. Still not perfect (if an offending img tag has no siblings, for example) - but this should help a bit, especially since the offending image will still be outlined. --- debugCSS.css | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 065dd11..c7c1c86 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -69,10 +69,10 @@ dt:empty:after, dd:empty:after, a:empty:after, a a:after, -img:not([alt]):after, -img:not([src]):after, -img[src=""]:after, -img[src="#"]:after, +img:not([alt]) + *:not(br):not(img):not(input):before, +img:not([src]) + *:not(br):not(img):not(input):before, +img[src=""] + *:not(br):not(img):not(input):before, +img[src="#"] + *:not(br):not(img):not(input):before, a:not([href]):after, a[href="#"]:after, a[href*=javascript\:]:after, @@ -106,8 +106,8 @@ center:after, u:after, font:after, map:after, -br + *:not(br):before, -br + br + *:before, +br + *:not(br):not(img):not(input):before, +br + br + *:not(br):not(img):not(input):before, b:after, i:after, blink:after, @@ -369,14 +369,14 @@ a a:after { content: 'A tag within another A tag - this looks like a bug'; } -img:not([alt]):after { +img:not([alt]) + *:not(br):not(img):not(input):before { background: #FFFF88; content: 'Image does not have an ALT attribute'; } -img:not([src]):after, -img[src=""]:after, -img[src="#"]:after { +img:not([src]) + *:not(br):not(img):not(input):before, +img[src=""] + *:not(br):not(img):not(input):before, +img[src="#"] + *:not(br):not(img):not(input):before, { background: #FF8888; content: 'IMG without proper SRC attribute. Serious implications for some browsers'; } @@ -631,12 +631,12 @@ map:after { content: 'Is MAP appropriate here?'; } -br + *:not(br):before { +br + *:not(br):not(img):not(input):before { background: #88FF88; content: 'Is BR appropriate here?'; } -br + br + *:before { +br + br + *:not(br):not(img):not(input):before { background: #88FF88; content: 'Should you be using a P tag?'; } From a1dbe8932cd73fd51d90366e961d4c5f1a48e84a Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 22 Jan 2014 11:47:56 -0800 Subject: [PATCH 16/23] Void element messages, table changes Void elements now try to display the error messages before the next non-void sibling element. If none are found, the message is not displayed (but the node is still highlighted). Thank you to thierryk@ for his suggestions on table accessibility: removing summary, requiring caption. --- debugCSS.css | 57 +++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index c7c1c86..1411161 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -31,14 +31,15 @@ /******************/ /* All errors should try to post a message explaining the problem. */ -table:not([summary]):after, +table[summary]:after, +table > *:first-child:not(caption):after, table > tr:after, table th:not([scope]):after, table thead td:after, table > colgroup ~ caption:after, -table > thead ~ colgroup:after, -table > tfoot ~ colgroup:after, -table > tbody ~ colgroup:after, +table > thead ~ colgroup + *:before, +table > tfoot ~ colgroup + *:before, +table > tbody ~ colgroup + *:before, table > thead ~ caption:after, table > tfoot ~ caption:after, table > tbody ~ caption:after, @@ -69,10 +70,10 @@ dt:empty:after, dd:empty:after, a:empty:after, a a:after, -img:not([alt]) + *:not(br):not(img):not(input):before, -img:not([src]) + *:not(br):not(img):not(input):before, -img[src=""] + *:not(br):not(img):not(input):before, -img[src="#"] + *:not(br):not(img):not(input):before, +img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src=""] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src="#"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, a:not([href]):after, a[href="#"]:after, a[href*=javascript\:]:after, @@ -101,13 +102,13 @@ ul > *:not(li):after, dl > *:not(dt):not(dd):after, form > *:not(fieldset):after, fieldset > *:not(legend):first-child:after, -iframe:not([title]):after, +iframe:not([title]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, center:after, u:after, font:after, map:after, -br + *:not(br):not(img):not(input):before, -br + br + *:not(br):not(img):not(input):before, +br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +br + br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, b:after, i:after, blink:after, @@ -263,9 +264,14 @@ marquee:after, element. */ -table:not([summary]):after { +table[summary]:after { background: #88FF88; - content: 'Should you have a SUMMARY attribute on your TABLE?'; + content: 'SUMMARY attribute is obsolete'; +} + +table > *:first-child:not(caption):after { + background: #88FF88; + content: 'Should you have a CAPTION on your TABLE?'; } table > tr:after { @@ -288,9 +294,9 @@ table > colgroup ~ caption:after { content: 'CAPTION must come before COLGROUP'; } -table > thead ~ colgroup:after, -table > tfoot ~ colgroup:after, -table > tbody ~ colgroup:after { +table > thead ~ colgroup + *:before, +table > tfoot ~ colgroup + *:before, +table > tbody ~ colgroup + *:before { background: #FFFF88; content: 'COLGROUP must come before THEAD, TFOOT and TBODY'; } @@ -369,14 +375,14 @@ a a:after { content: 'A tag within another A tag - this looks like a bug'; } -img:not([alt]) + *:not(br):not(img):not(input):before { +img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { background: #FFFF88; content: 'Image does not have an ALT attribute'; } -img:not([src]) + *:not(br):not(img):not(input):before, -img[src=""] + *:not(br):not(img):not(input):before, -img[src="#"] + *:not(br):not(img):not(input):before, { +img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src=""] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src="#"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { background: #FF8888; content: 'IMG without proper SRC attribute. Serious implications for some browsers'; } @@ -449,8 +455,8 @@ fieldset > *:not(legend):first-child:after { content: 'Should your FIELDSET be using a LEGEND?'; } -iframe:not([title]):after { - background: #88FF88; +iframe:not([title]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #FFFF88; content: 'IFRAME lacks TITLE attribute'; } @@ -631,12 +637,12 @@ map:after { content: 'Is MAP appropriate here?'; } -br + *:not(br):not(img):not(input):before { +br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(img):not(input):first-of-type:before { background: #88FF88; content: 'Is BR appropriate here?'; } -br + br + *:not(br):not(img):not(input):before { +br + br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { background: #88FF88; content: 'Should you be using a P tag?'; } @@ -811,7 +817,8 @@ marquee { outline: 5px solid #FFFF88; } -table:not([summary]), +table[summary], +table > *:first-child:not(caption), table th:not([scope]), table thead td, table > tr:first-child:last-child, From c08f1e23c18e12e31b2c430a35fdb8f4dca8c41a Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 22 Jan 2014 14:24:19 -0800 Subject: [PATCH 17/23] Add a notice to show error / warning / notice count --- debugCSS.css | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/debugCSS.css b/debugCSS.css index 1411161..13173e8 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -242,7 +242,8 @@ marquee:after, *[id*=\{]:after, *[id*=\}]:after, *[id*=\|]:after, -*[id*=\`]:after { +*[id*=\`]:after, +body:after { border: 1px solid #000; color: #000; display: block; @@ -677,6 +678,7 @@ img[src="#"], *[id*=\\], *[id*=\.], *[id*=\#] { + counter-increment: error; outline: 5px solid #FF8888; } @@ -814,6 +816,7 @@ u, font, blink, marquee { + counter-increment: warning; outline: 5px solid #FFFF88; } @@ -882,9 +885,24 @@ i, *[id*=Yellow], *[id*=White], *[id*=Black] { + counter-increment: notice; outline: 5px solid #88FF88; } +body { + counter-reset: error warning notice; +} + +body:after { + background: #FFF; + content: 'Errors: ' counter(error) ' | Warnings: ' counter(warning) ' | Notices: ' counter(notice); + font-size: 125%; + right: 1em; + outline: 5px solid #000; + position: fixed; + bottom: 1em; +} + /*********/ /* EXTRA */ /*********/ From dd2b626fc0d2d1d9f8a3fab930b080152e1f708c Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 23 Jan 2014 10:41:12 -0800 Subject: [PATCH 18/23] Image and iframe are ok to have explicit height / width During initial rendering, having explicit height and width attributes for iframes or images allow for them to take up rendered space before styling can be applied. Whitelist those from the check for inline height / width attributes (most other elements should probably add these values to the CSS). --- debugCSS.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 13173e8..b02cb21 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -56,8 +56,8 @@ table[bgcolor]:after, table[border]:after, table[cellpadding]:after, table[cellspacing]:after, -*[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ -*[height]:after, +*:not(img):not(iframe)[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ +*:not(img):not(iframe)[height]:after, *[border]:after, div:empty:after, span:empty:after, @@ -350,8 +350,8 @@ table[bgcolor]:after, table[border]:after, table[cellpadding]:after, table[cellspacing]:after, -*[width]:after, -*[height]:after, +*:not(img):not(iframe)[width]:after, +*:not(img):not(iframe)[height]:after, *[border]:after { background: #FFFF88; content: 'Element has inline style'; @@ -700,8 +700,8 @@ table[bgcolor], table[border], table[cellpadding], table[cellspacing], -*[width], -*[height], +*:not(img):not(iframe)[width], +*:not(img):not(iframe)[height], *[border], div:empty:after, span:empty, From fe1345163d4adeaef77a81b44e9fd1c31dd4420d Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 23 Jan 2014 11:26:10 -0800 Subject: [PATCH 19/23] Highlight any empty non-void element Instead of blacklisting most likely offending tags, let's whitelist tags we know cannot be offending. --- debugCSS.css | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index b02cb21..f8e69b2 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -59,16 +59,7 @@ table[cellspacing]:after, *:not(img):not(iframe)[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ *:not(img):not(iframe)[height]:after, *[border]:after, -div:empty:after, -span:empty:after, -p:empty:after, -ul:empty:after, -ol:empty:after, -dl:empty:after, -li:empty:after, -dt:empty:after, -dd:empty:after, -a:empty:after, +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty:after, a a:after, img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, @@ -357,18 +348,9 @@ table[cellspacing]:after, content: 'Element has inline style'; } -div:empty:after, -span:empty:after, -p:empty:after, -ul:empty:after, -ol:empty:after, -dl:empty:after, -li:empty:after, -dt:empty:after, -dd:empty:after, -a:empty:after { +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty:after { background: #FFFF88; - content: 'Element has no content. Is this necessary?'; + content: 'Element is empty. Is this necessary?'; } a a:after { @@ -703,16 +685,7 @@ table[cellspacing], *:not(img):not(iframe)[width], *:not(img):not(iframe)[height], *[border], -div:empty:after, -span:empty, -p:empty, -ul:empty, -ol:empty, -dl:empty, -li:empty, -dt:empty, -dd:empty, -a:empty, +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty, img:not([alt]), a:not([href]), a[href="#"], From afbace055ac259a7aa7e53308cc3945d0454ebf3 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 29 Jan 2014 11:01:11 -0800 Subject: [PATCH 20/23] Allow textarea elements to be :empty --- debugCSS.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index f8e69b2..412926b 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -59,7 +59,7 @@ table[cellspacing]:after, *:not(img):not(iframe)[width]:after, /* Acceptable for transitional doctypes, but should probably be relegated to CSS */ *:not(img):not(iframe)[height]:after, *[border]:after, -*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty:after, +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):not(textarea):empty:after, a a:after, img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, @@ -348,7 +348,7 @@ table[cellspacing]:after, content: 'Element has inline style'; } -*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty:after { +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):not(textarea):empty:after { background: #FFFF88; content: 'Element is empty. Is this necessary?'; } @@ -685,7 +685,7 @@ table[cellspacing], *:not(img):not(iframe)[width], *:not(img):not(iframe)[height], *[border], -*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):empty, +*:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):not(textarea):empty, img:not([alt]), a:not([href]), a[href="#"], From d82a158941f5129e56fe56413149fce219be48d0 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 10 May 2014 12:08:02 -0700 Subject: [PATCH 21/23] Shorthand colors, added a few rules Shorthanded hex colors. Removed comment about red severity not in use (as it is, now). Added checks for unencoded &, spacer.gif, script without type, style without type. --- debugCSS.css | 142 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 54 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 412926b..0bcfa55 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -18,12 +18,11 @@ broken, malformed or legacy (X)HTML. Not all "errors" are created equally, so they are color coded to highlight severity. Green is "probably not a big problem", yellow is "worth looking at" and red is "you really should fix - this." Red severity is currently not used, but can be made available for - future revisions. + this." - Red: #FF8888; - Yellow: #FFFF88; - Green: #88FF88; + Red: #F88; + Yellow: #FF8; + Green: #8F8; */ /******************/ @@ -65,6 +64,9 @@ img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(i img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src=""] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src="#"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src="spacer.gif"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +img[src*="&"]:not([src*="&"]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +a[href*="&"]:not([href*="&"]):after, a:not([href]):after, a[href="#"]:after, a[href*=javascript\:]:after, @@ -104,6 +106,8 @@ b:after, i:after, blink:after, marquee:after, +script:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +style:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, *[class^="1"]:after, *[class^="2"]:after, *[class^="3"]:after, @@ -257,82 +261,82 @@ body:after { */ table[summary]:after { - background: #88FF88; + background: #8F8; content: 'SUMMARY attribute is obsolete'; } table > *:first-child:not(caption):after { - background: #88FF88; + background: #8F8; content: 'Should you have a CAPTION on your TABLE?'; } table > tr:after { - background: #FFFF88; + background: #FF8; content: 'TABLE does not have a TBODY'; } table th:not([scope]):after { - background: #88FF88; + background: #8F8; content: 'Should TH have a SCOPE attribute (ROW or COL)? OK if using ID and HEADERS'; } table thead td:after { - background: #88FF88; + background: #8F8; content: 'Cells in THEAD should be TH'; } table > colgroup ~ caption:after { - background: #FFFF88; + background: #FF8; content: 'CAPTION must come before COLGROUP'; } table > thead ~ colgroup + *:before, table > tfoot ~ colgroup + *:before, table > tbody ~ colgroup + *:before { - background: #FFFF88; + background: #FF8; content: 'COLGROUP must come before THEAD, TFOOT and TBODY'; } table > thead ~ caption:after, table > tfoot ~ caption:after, table > tbody ~ caption:after { - background: #FFFF88; + background: #FF8; content: 'CAPTION must come before THEAD, TFOOT and TBODY'; } table > tbody:first-child:after { - background: #88FF88; + background: #8F8; content: 'Do you need a THEAD or TFOOT?'; } table > tfoot ~ thead:after { - background: #FFFF88; + background: #FF8; content: 'TFOOT should come after THEAD'; } table > tbody ~ tfoot:after { - background: #FFFF88; + background: #FF8; content: 'TBODY should come after TFOOT'; } table > tbody ~ thead:after { - background: #FFFF88; + background: #FF8; content: 'TBODY should come after THEAD'; } table > tr:only-child:after, table > tbody > tr:only-child:after { - background: #88FF88; + background: #8F8; content: 'Only one TR in TABLE. Are you using it for layout?'; } table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption):after { - background: #FFFF88; + background: #FF8; content: 'Only THEAD/TFOOT/TBODY/COLGROUP/CAPTION/TR can be children of a TABLE'; } colgroup *:not(col):after { - background: #FFFF88; + background: #FF8; content: 'Only COLs can be children of COLGROUP'; } @@ -344,35 +348,50 @@ table[cellspacing]:after, *:not(img):not(iframe)[width]:after, *:not(img):not(iframe)[height]:after, *[border]:after { - background: #FFFF88; + background: #FF8; content: 'Element has inline style'; } *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):not(textarea):empty:after { - background: #FFFF88; + background: #FF8; content: 'Element is empty. Is this necessary?'; } a a:after { - background: #FF8888; + background: #F88; content: 'A tag within another A tag - this looks like a bug'; } img:not([alt]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { - background: #FFFF88; + background: #FF8; content: 'Image does not have an ALT attribute'; } img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src=""] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src="#"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { - background: #FF8888; + background: #F88; content: 'IMG without proper SRC attribute. Serious implications for some browsers'; } +img[src="spacer.gif"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #FF8; + content: 'spacer.gif used - is this used for layout?'; +} + +img[src*="&"]:not([src*="&"]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #F88; + content: 'Unencoded & in img src'; +} + +a[href*="&"]:not([href*="&"]):after { + background: #F88; + content: 'Unencoded & in anchor'; +} + a[href="#"]:after, a:not([href]):after { - background: #FFFF88; + background: #FF8; content: 'Anchor tag is # or does not exist - does not degrade gracefully'; } @@ -380,22 +399,22 @@ a[href*=javascript\:]:after, a[onclick]:after, a[onmouseover]:after, a[onmouseout]:after { - background: #FFFF88; + background: #FF8; content: 'Inline JS on anchor'; } label:not([for]):after { - background: #FFFF88; + background: #FF8; content: 'Should LABEL have a FOR attribute?'; } nav:not([role]):after { - background: #FFFF88; + background: #FF8; content: 'NAV element should have a ROLE attribute'; } div[role="img"]:not([aria-label]):after { - background: #FFFF88; + background: #FF8; content: 'DIV used as image should have ARIA-LABEL'; } @@ -413,40 +432,40 @@ html[xmlns] a h3:after, html[xmlns] a h4:after, html[xmlns] a h5:after, html[xmlns] a h6:after { - background: #FFFF88; + background: #FF8; content: 'Block level element within inline element'; } ol > *:not(li):after, ul > *:not(li):after { - background: #FFFF88; + background: #FF8; content: 'Only LIs can be children of UL or OL'; } dl > *:not(dt):not(dd):after { - background: #FFFF88; + background: #FF8; content: 'Only DT/DD can be children of a DL'; } form > *:not(fieldset):after { - background: #88FF88; + background: #8F8; content: 'Should you be using a FIELDSET?'; } fieldset > *:not(legend):first-child:after { - background: #88FF88; + background: #8F8; content: 'Should your FIELDSET be using a LEGEND?'; } iframe:not([title]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { - background: #FFFF88; + background: #FF8; content: 'IFRAME lacks TITLE attribute'; } center:after, u:after, font:after { - background: #FFFF88; + background: #FF8; content: 'Deprecated tag used'; } @@ -460,7 +479,7 @@ font:after { *[class^="8"]:after, *[class^="9"]:after, *[class^="0"]:after { - background: #FFFF88; + background: #FF8; content: 'Class name cannot start with number'; } @@ -474,7 +493,7 @@ font:after { *[id^="8"]:after, *[id^="9"]:after, *[id^="0"]:after { - background: #FFFF88; + background: #FF8; content: 'ID cannot start with number'; } @@ -504,7 +523,7 @@ font:after { *[class*=Yellow]:after, *[class*=White]:after, *[class*=Black]:after { - background: #88FF88; + background: #8F8; /* I know that these aren't necessarily bad, but probably worth highlighting */ content: attr(class) ' has implied style meaning - should you be naming it differently?'; } @@ -535,7 +554,7 @@ font:after { *[id*=Yellow]:after, *[id*=White]:after, *[id*=Black]:after { - background: #88FF88; + background: #8F8; /* I know that these aren't necessarily bad, but probably worth highlighting */ content: attr(id) ' has implied style meaning - should you be naming it differently?'; } @@ -543,14 +562,14 @@ font:after { *[class*=\\]:after, *[class*=\.]:after, *[class*=\#]:after { - background: #FF8888; + background: #F88; content: 'Classname has an ambiguous character'; } *[id*=\\]:after, *[id*=\.]:after, *[id*=\#]:after { - background: #FF8888; + background: #F88; content: 'ID has an ambiguous character'; } @@ -580,7 +599,7 @@ font:after { *[class*=\}]:after, *[class*=\|]:after, *[class*=\`]:after { - background: #FFFF88; + background: #FF8; content: 'Class has an illegal character'; } @@ -610,38 +629,48 @@ font:after { *[id*=\}]:after, *[id*=\|]:after, *[id*=\`]:after { - background: #FFFF88; + background: #FF8; content: 'ID has an illegal character'; } /* These may not be "wrong", but let's bug you anyway. */ map:after { - background: #88FF88; + background: #8F8; content: 'Is MAP appropriate here?'; } br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(img):not(input):first-of-type:before { - background: #88FF88; + background: #8F8; content: 'Is BR appropriate here?'; } br + br ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { - background: #88FF88; + background: #8F8; content: 'Should you be using a P tag?'; } b:after, i:after { - background: #88FF88; + background: #8F8; content: 'Should you be using STRONG or EM?'; } blink:after, marquee:after { - background: #FFFF88; + background: #FF8; content: 'Should you be using STRONG or EM?'; } +script:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #8F8; + content: 'script tag without type defined'; +} + +style:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #8F8; + content: 'style tag without type defined'; +} + /******************/ /* ERROR OUTLINES */ /******************/ @@ -654,6 +683,8 @@ a a, img:not([src]), img[src=""], img[src="#"], +img[src*="&"]:not([src*="&"]), +a[href*="&"]:not([href*="&"]), *[class*=\\], *[class*=\.], *[class*=\#], @@ -661,7 +692,7 @@ img[src="#"], *[id*=\.], *[id*=\#] { counter-increment: error; - outline: 5px solid #FF8888; + outline: 5px solid #F88; } table > tr, @@ -687,6 +718,7 @@ table[cellspacing], *[border], *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):not(textarea):empty, img:not([alt]), +img[src="spacer.gif"], a:not([href]), a[href="#"], a[href*=javascript\:], @@ -788,9 +820,11 @@ center, u, font, blink, -marquee { +marquee, +script:not([type]), +style:not([type]) { counter-increment: warning; - outline: 5px solid #FFFF88; + outline: 5px solid #FF8; } table[summary], @@ -859,7 +893,7 @@ i, *[id*=White], *[id*=Black] { counter-increment: notice; - outline: 5px solid #88FF88; + outline: 5px solid #8F8; } body { From c3730d22760b042dc4e93d03f7c19d3118bdfc88 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 10 May 2014 13:24:42 -0700 Subject: [PATCH 22/23] Comment out check for unencoded & MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems some (most?) browsers convert & to & behind the scenes upon render, thereby making this condition fail for any URL with “&” in it (encoded or not). Commenting out since this is still a good check, but is causing false positives. --- debugCSS.css | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/debugCSS.css b/debugCSS.css index 0bcfa55..54e879e 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -65,8 +65,10 @@ img:not([src]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(i img[src=""] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src="#"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, img[src="spacer.gif"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +/* img[src*="&"]:not([src*="&"]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, a[href*="&"]:not([href*="&"]):after, +*/ a:not([href]):after, a[href="#"]:after, a[href*=javascript\:]:after, @@ -379,6 +381,11 @@ img[src="spacer.gif"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr content: 'spacer.gif used - is this used for layout?'; } +/* + * Some (most?) browsers convert & to & once rendered. + */ + +/* img[src*="&"]:not([src*="&"]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { background: #F88; content: 'Unencoded & in img src'; @@ -388,7 +395,7 @@ a[href*="&"]:not([href*="&"]):after { background: #F88; content: 'Unencoded & in anchor'; } - +*/ a[href="#"]:after, a:not([href]):after { background: #FF8; @@ -683,8 +690,10 @@ a a, img:not([src]), img[src=""], img[src="#"], +/* img[src*="&"]:not([src*="&"]), a[href*="&"]:not([href*="&"]), +*/ *[class*=\\], *[class*=\.], *[class*=\#], From 5046a2f76787b21cac584681e0c5ad9350461483 Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 29 Jul 2014 21:55:48 -0700 Subject: [PATCH 23/23] Extra checks for script and style tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a script tag isn’t at the bottom of your body - and if you have any style tags in your body, we should let you know. --- debugCSS.css | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/debugCSS.css b/debugCSS.css index 54e879e..cb5a971 100644 --- a/debugCSS.css +++ b/debugCSS.css @@ -110,6 +110,8 @@ blink:after, marquee:after, script:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, style:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, +body script ~ *:not(script):before, +body style ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before, *[class^="1"]:after, *[class^="2"]:after, *[class^="3"]:after, @@ -381,21 +383,6 @@ img[src="spacer.gif"] ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr content: 'spacer.gif used - is this used for layout?'; } -/* - * Some (most?) browsers convert & to & once rendered. - */ - -/* -img[src*="&"]:not([src*="&"]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { - background: #F88; - content: 'Unencoded & in img src'; -} - -a[href*="&"]:not([href*="&"]):after { - background: #F88; - content: 'Unencoded & in anchor'; -} -*/ a[href="#"]:after, a:not([href]):after { background: #FF8; @@ -678,6 +665,16 @@ style:not([type]) ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):no content: 'style tag without type defined'; } +body script ~ *:not(script):before { + background: #8F8; + content: 'script tag should be at the bottom of your body'; +} + +body style ~ *:not(area):not(base):not(br):not(col):not(embed):not(hr):not(iframe):not(img):not(input):first-of-type:before { + background: #8F8; + content: 'CSS should be in your head'; +} + /******************/ /* ERROR OUTLINES */ /******************/ @@ -829,9 +826,7 @@ center, u, font, blink, -marquee, -script:not([type]), -style:not([type]) { +marquee { counter-increment: warning; outline: 5px solid #FF8; } @@ -900,7 +895,11 @@ i, *[id*=Green], *[id*=Yellow], *[id*=White], -*[id*=Black] { +*[id*=Black], +script:not([type]), +style:not([type]), +body script ~ *:not(script), +body style { counter-increment: notice; outline: 5px solid #8F8; }