Es begann, wie so viele Dinge, mit einem albernen Gespräch. In diesem Fall sprach ich mit unserem Front End Technology Competency Director (auch bekannt als „Boss Man“) Mundi Morgado.
Es lief ungefähr so…
Mundi Morgado Ich möchte, dass Sie einen visuellen Screenreader erstellen.
Nathan Smith Wer, was, wie bitte?
Mundi Morgado Ich möchte eine CSS-Bibliothek, mit der Sie die Struktur eines Dokuments sehen können. Sie sollte keine class verwenden, damit Sie gezwungen sind, sich auf Semantik zu konzentrieren. Machen Sie sie außerdem themenbezogen.
Nathan Smith Sicher, lassen Sie mich sehen, was mir einfällt.
Eine Woche später haben wir das, was wir jetzt nennen
Construct.css: Die Wegwerf-CSS-Bibliothek ohne Klasse
Warum wegwerfbar? Nun, es ist nicht wirklich als ein vollwertiges, produktionsbereites Stil-Framework gedacht. Vielmehr ist es wie Stützräder für Dokumenten-Semantik, mit einigen Stoßstangen (denken Sie an Bowling), um Sie auf dem richtigen Weg zu halten.
Es ist Teil unserer fortlaufenden Bemühungen bei TandemSeven, die Code-Kompetenz in unserer gesamten Organisation zu fördern. Da mehr unserer UX-Designer beginnen, Verantwortung für die Barrierefreiheit und Semantik eines Projekts zu übernehmen, ist es sinnvoll, dass wir auf eine Weise aufbauen, die eine kollaborativere Zusammenarbeit zwischen UX und Entwicklung ermöglicht.
Construct hat vier Hauptaspekte.
Construct: "Basic"
Erstens gibt es die Basisdatei Construct.css, die den meisten gängigen HTML-Elementen ein passable Basis-Aussehen und -Gefühl verleiht. Sehen Sie sich dieses Beispiel einer Basis-Seite an.
Construct: "Boxes"

Zweitens gibt es construct.boxes.css. Dies unterscheidet visuell ansonsten unsichtbare semantische Elemente, wie z.B. header, main, nav, usw. So kann man sehen, wo diese Elemente sind (oder nicht sind), während eine Seite erstellt wird. Hier ist eine Seite mit umrissenen semantischen Boxen.
Construct: "Theme"

Drittens ist das Theming über construct.theme.css möglich. Dies ist größtenteils nur ein Beispiel – inspiriert von PaperCSS) – wie man die Benutzeroberfläche "handgezeichnet" aussehen lässt, um zu verhindern, dass Beobachter zu sehr auf das Aussehen und Gefühl fixiert sind, anstatt auf die Semantik eines Dokuments. Hier ist das Beispiel-Theme in Aktion.
Construct: "Debug"

Zuletzt gibt es eine Datei construct.debug.css, die ungültige und/oder problematische Markup hervorhebt und beanstandet. Hier ist ein scheußliches Beispiel für "alles" falsch Gelaufene auf einer einzigen HTML-Seite. Dies wurde von a11y.css inspiriert, obwohl es sich darin unterscheidet, was als bemerkenswert gilt.
Zum Beispiel beanstanden wir "Div-itis", wenn mehrere div:only-child ineinander verschachtelt wurden. Wir sind auch der Meinung, dass type="checkbox" in einem <label> enthalten sein sollte. Dies dient der maximalen Klickbarkeit innerhalb einer ansonsten toten Leerstelle zwischen einer Checkbox (oder einem Radiobutton) und ihrem Text-Label.
Jede oder alle dieser CSS-Dateien können einzeln oder in Kombination miteinander angewendet werden. Es gibt auch ein Lesezeichen (beschriftet mit "GET Construct!") auf der Construct-Homepage, das Sie verwenden können, um Ergebnisse für jede beliebige Webseite zu erhalten.

Das Lesezeichen ruft remote auf
sanitize.cssconstruct.cssconstruct.boxes.cssconstruct.debug.css
Unser "Reset" – Sanitize.css
Ein kurzes Wort zu Santitize.css: Es wurde von meinem Kollegen Jonathan Neal (Autor von Normalize.css) erstellt, um einen semi-eigenwilligen CSS-Reset zu haben. Das bedeutet, es enthält viele Standardeinstellungen, die wir als Entwickler sowieso schreiben, so dass es eine gute Ausgangsbasis ist.
Technisch gesprochen
Okay, nachdem wir nun das "Warum" besprochen haben, lass uns ins "Wie" eintauchen.
Grundsätzlich dreht sich alles um die Verwendung (Missbrauch?) der Pseudo-Elemente ::before und ::after. Um beispielsweise den Namen eines Block-Level-Tags anzuzeigen, verwenden wir dieses CSS.
Semantische Tags (mit ::before)
Hier ist eine gekürzte Version der Datei construct.boxes.css zur Kürze. Sie bewirkt, dass das <section>-Tag einen gestrichelten Rand hat und sein Tag-Name in der oberen linken Ecke angezeigt wird.
section {
border: 1px dashed #f0f;
display: block;
margin-bottom: 2rem; /* 20px. */
padding: 2rem; /* 20px. */
position: relative;
}
section > :last-child {
margin-bottom: 0;
}
section::before {
background: #fff;
color: #f0f;
content: "section";
font-family: "Courier", monospace;
font-size: 1rem; /* 10px. */
letter-spacing: 0.1rem; /* 1px. */
line-height: 1.3;
text-transform: uppercase;
position: absolute;
top: 0;
left: 0.3rem; /* 3px. */
}
Warnmeldungen (mit ::after)
Ebenso ist hier ein Code-Schnipsel aus der Datei construct.debug.css, der die Markup-Warnmeldungen steuert. Dieses spezielle Beispiel bewirkt, dass <script>-Tags angezeigt werden, die möglicherweise weiter optimiert werden müssen oder die Aufmerksamkeit des Entwicklers erfordern: Inline-JavaScript und/oder externe src ohne async.
Im Fall von Inline-JS setzen wir die font-size und line-height auf 0, da wir das Element sichtbar machen. Wir reißen den Text von der Seite mit text-indent: -99999px, nur um sicherzustellen, dass er nicht angezeigt wird. Wir möchten nicht, dass dieser zufällige JavaScript-Code neben legitimen Seiteninhalten angezeigt wird.
(Bitte tun Sie das niemals für "echte" Inhalte. Es ist nur ein Hack, okay?)
Um unsere Fehlermeldung anzuzeigen, müssen wir jedoch die font-size und line-height wieder auf Nicht-Null-Werte setzen und unseren text-indent entfernen. Dann sorgen wir mit etwas mehr absoluter Positionierung dafür, dass die Meldung sichtbar ist. So können wir inmitten des restlichen Seiteninhalts sehen, wo wir (über den DOM-Inspektor) nach dem Einfügepunkt des <script> suchen müssen.
script:not([src]),
script[src]:not([async]),
script[src^="http:"] {
color: transparent;
display: block;
font-size: 0;
height: 2rem; /* 20px. */
line-height: 0;
margin-bottom: 2rem; /* 20px. */
position: relative;
text-indent: -99999px;
width: 100%;
}
script:not([src])::after,
script[src]:not([async])::after,
script[src^="http:"]::after {
background: #f00;
color: #fff;
display: inline-block;
font-family: Verdana, sans-serif;
font-size: 1.1rem; /* 11px. */
font-weight: normal;
left: 0;
line-height: 1.5;
padding-left: 0.5rem; /* 5px. */
padding-right: 0.5rem; /* 5px. */
pointer-events: none;
position: absolute;
text-decoration: none;
text-indent: 0;
top: 100%;
white-space: nowrap;
z-index: 1;
}
body script:not([src])::after,
body script[src]:not([async])::after,
body script[src^="http:"]::after {
top: 0;
}
script:not([src])::after {
content:
'Move inline <script> to external *.js file'
;
}
script[src]:not([async])::after {
content:
'Consider [async] for <script> with [src="…"]'
;
}
script[src]:not([src=""]):not([async])::after {
content:
'Consider [async] for <script> with [src="' attr(src) '"]'
;
}
script[src^="http:"]::after {
content:
'Consider "https:" for <script> with [src="' attr(src) '"]'
;
}
Hinweis: Manche Skripte müssen synchron geladen werden. Sie möchten nicht, dass Ihr "App"-Code vor Ihrem "Framework"-Code geladen wird. Tatsächlich ist vielleicht auch Inline-JS in Ordnung, besonders wenn Sie Super-Speed-Optimierungen für den kritischen Rendering-Pfad durchführen. Diese Warnungen sind "dumm" in dem Sinne, dass sie nur über CSS-Selektoren übereinstimmen. Nehmen Sie sie mit Vorsicht, Ihre Ergebnisse können variieren, usw.
JS-Lesezeichen
Das erwähnte JS-Lesezeichen findet alle <link rel="stylesheet">- und <style>-Tags auf der Seite und macht sie unwirksam. Dies ermöglicht es uns, unser eigenes CSS einzufügen, um die Kontrolle zu übernehmen, sodass die einzigen angewendeten Stile diejenigen sind, die direkt über Construct bereitgestellt werden.
Die Magie wird dadurch erreicht, dass rel="stylesheet" zu rel="" geändert wird. Wenn eine externe Stylesheet-Datei nicht als solche identifiziert wird, wird der Browser ihre Stile nicht auf die Seite anwenden, selbst wenn sie zwischengespeichert ist. Ebenso zerstören wir den Inhalt von Inline-<style>-Tags, indem wir innerHTML auf eine leere Zeichenfolge setzen.
Dadurch bleiben die Tags selbst erhalten, denn wir wollen immer noch validieren, dass keine <link>- oder <style>-Tags im <body> vorhanden sind.
Wir prüfen auch, ob nicht zu viele <style>-Tags im <head> verwendet werden. Wir erlauben einen, da er für den kritischen Rendering-Pfad verwendet werden könnte. Wenn ein Build-Prozess zum Generieren einer Seite mit konsolidierten Inline-Stilen vorhanden ist, dann werden diese wahrscheinlich über ein einzelnes Tag ausgegeben.
<a href="javascript:(
function (d) {
var f = Array.prototype.forEach;
var linkTags = d.querySelectorAll('[rel=\'stylesheet\']');
var styleTags = d.querySelectorAll('style');
f.call(linkTags, function (x) {
x.rel = '';
});
f.call(styleTags, function (x) {
x.innerHTML = '';
});
var newLink = d.createElement('link');
newLink.rel = 'stylesheet';
newLink.href =
'https://t7.github.io/construct.css/css/bookmarklet.css';
d.head.appendChild(newLink);
}
)(document);">
GET Construct!
</a>
Geh hin, hol dir Construct!
Das deckt so ziemlich alles ab. Es ist ein einfaches Drop-in, das Ihnen hilft, Ihre Dokumenten-Semantik zu visualisieren und möglicherweise problematische Markup zu debuggen.
Ich habe auch festgestellt, dass es super Spaß macht, es zu benutzen. Ein schneller Klick auf das Lesezeichen auf einer beliebigen Seite liefert normalerweise viele Dinge, die verbessert werden könnten.
Zum Beispiel sieht die CNN-Website mit angewendetem Construct so aus...

P.S. Rufen Sie die Sicherheit an!
Wenn Sie dies mit der Twitter-Website ausprobieren, fragen Sie sich vielleicht, warum es nicht funktioniert. Wir waren anfangs auch verwirrt. Es hat mit der Content Security Policy (CSP) der Website zu tun. Diese kann verwendet werden, um das Laden von externem CSS und/oder JavaScript zu verhindern und sichere Domains zuzulassen.
Dies kann entweder auf Serverebene oder über ein <meta>-Tag im <head> eingestellt werden.
<meta http-equiv="Content-Security-Policy" content="…" />
Lesen Sie hier mehr über CSP.
Ich weiß, was Sie denken...
Kann man dieses
meta-Tag nicht einfach mit JS zerstören?
Im Fall von Twitter wird es vom Server ausgegeben. Selbst wenn es im HTML wäre, hat die Zerstörung keinen Einfluss auf das tatsächliche Verhalten des Browsers. Es ist gesperrt.
Okay, also...
Kann man nicht sein eigenes Sicherheits-
meta-Tag einfügen und es überschreiben?
Man könnte meinen. Aber glücklicherweise nein. Sobald eine CSP vom Browser für diese Seite akzeptiert wurde, kann sie nicht mehr überschrieben werden. Das ist wahrscheinlich gut so, auch wenn es unseren Spaß ruiniert.
Ich nehme an, das wäre so, als würde man sich mehr Wünsche wünschen. Das verstößt gegen die Regeln des Dschinns!
Das ist fantastisch! Webdesign muss in Bezug auf Semantik und Organisation meinungsfreudiger werden. Neben der übermäßigen Abhängigkeit von Klassen/beliebigen Attributen gibt es auch viel zu viel Abhängigkeit von verschachtelten Elementen.
Mein größter Dorn im Auge sind wahrscheinlich Seiten, die Aufzählungslisten verwenden könnten, stattdessen aber 7000 verschachtelte Divs oder Tabellen oder was auch immer haben. Die drei am wenigsten genutzten Präsentationselemente, die seit HTML 4 verfügbar sind, sind
<dl>s und<fieldset>s.Tolles Projekt!
Das ist großartig. Es erinnerte mich an Adam Morses Pesticide-Projekt, aber es ist viel robuster, z.B. gibt es Feedback zu Elementtypen usw., während Pesticide auf eindeutig farbige Umrandungen für schnelles Debugging fokussiert war.
Ich habe ein Issue eröffnet und einen Pull Request für einige falsche Fehler bei Beschreibunglisten gemacht. Aber tolle Arbeit. Ich habe dies heute bereits gut genutzt.
Okay, das ist großartig.
Verdammt genial. Ich habe nicht einmal persönlich eine Verwendung dafür, aber es ist trotzdem aufregend. CSS ist in gewisser Weise meine Lieblingsprogrammiersprache, und das ist ein großartiger praktischer Anwendungsfall, um ihre Fähigkeiten zu demonstrieren (hah).
Das ist so nett! Danke.
Ich benutze Pesticide von Zeit zu Zeit, es ist ein großartiges Werkzeug, um Ihr Layout zu visualisieren, und es kann Ihnen zeigen, wann jemand versucht, sich in CSS zu täuschen, indem er gefälschte Layouts erzwingt, was später schwer zu behebende Fehler verursacht. Aber ich hatte immer das Gefühl, es könnte mehr sein. Ich würde mir wünschen, dass dies eine einfache Ein/Aus-Browsererweiterung wie Pesticide wäre.
Sehr cooles Projekt, liebe das Theme! Und danke für die Erwähnung von PaperCSS :)