Schlechtester Name aller Zeiten, aber ich hatte Schwierigkeiten, ihm einen Namen zu geben, und das schien zu passen. Dies ist das Endergebnis

Es deckt eine Vielzahl von Dingen ab, die ich interessant fand
- Die neue Syntax für die Elementerstellung von jQuery 1.4, die ziemlich cool ist und die wir noch nicht abgedeckt haben
- Schreiben eines kleinen Plugins, um wiederholten Code zu verhindern (und im Geiste von jQuery zu bleiben)
- Berührt, was ich langsam als objektorientiertes CSS betrachte
Das Ziel
Was wir hier haben, sind einige Inhaltsboxen. Das Ziel ist, dass sie sich verdunkeln und ein Link genau in der Mitte erscheint, wenn man mit der Maus darüber fährt. Mir ist bewusst, dass dies für viele Dinge keine ideale UI-Wahl ist. Dinge unleserlich zu machen, wenn man mit der Maus darüber fährt, ist eine ungewöhnliche Designentscheidung. Aber es könnte unter bestimmten Umständen perfekt sein. Moral von der Geschichte: Treffen Sie keine voreiligen Urteile aufgrund von Demos.
HTML
Nur ein Div mit etwas Text darin…
<div class="widget widget-one rounded">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>
Was Sie tun möglicherweise möchten, ist, in jedes Widget einen Hyperlink einzufügen, der zur selben Stelle führt wie der Link, den wir mit JavaScript hinzufügen werden (Degradierbarkeit). Auch dies ist nur eine Demo und die Umstände werden in Live-Szenarien anders sein.
CSS
Ich nenne unsere kleinen Boxen „Widgets“. Beachten Sie, dass ich dem Div-Wrapper die Klasse widget gegeben habe. Dies ist das grundlegende Widget
.widget {
width: 300px;
padding: 20px;
border: 1px solid #999;
margin: 0 20px 20px 0;
float: left;
position: relative;
}
Beachten Sie jedoch, dass in der Live-Demo und im obigen Bild die Widgets abgerundete Ecken haben. Wir alle wissen inzwischen, wie man abgerundete Ecken in CSS erstellt. Es gibt den Standardborder-radiusund seine verwandten Anbietererweiterungen. Warum fügen wir sie nicht direkt in die Widget-CSS selbst ein? Hier kommt das objektorientierte CSS ins Spiel…
Die Art und Weise, wie mein Gehirn und CSS *typischerweise* funktionieren, ist, dass ich versuche, das HTML so sauber und semantisch wie möglich zu halten. Mir wurde immer beigebracht, dass die Verwendung eines CSS-Klassennamens wie „red“ eine mega schlechte Praxis ist, weil „red“ nicht semantisch, sondern spezifisch beschreibend ist. Stattdessen sollten Sie etwas wie „important“ oder „warning“ verwenden, denn wenn Sie später entscheiden, dass diese Dinge grün statt rot sein sollen, ist Ihre „red“-Klasse peinlich irrelevant.
Objektorientiertes CSS wirft einige dieser Überlegungen über den Haufen. Objektorientiertes CSS verwendet Klassennamen speziell, um Designmerkmale dieses „Objekts“ (Seitenelement) zu beschreiben. Beachten Sie, dass ich dem Widget auch die Klasse „rounded“ gegeben habe. In unserem CSS wird die Klasse rounded dies sein
.rounded {
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
}
Gotteslästerung? Ich dachte früher, aber in letzter Zeit gefällt mir dieser Ansatz wirklich gut. Es kann sein, dass 20 Dinge auf der Seite „gerundet“ sind. Jetzt müssen wir nur noch die gerundete Klasse auf jedes davon anwenden, und sie werden gerundet. Müssen Sie diesen Randradius anpassen? Passen Sie ihn an einer Stelle an, und alle gerundeten Objekte stimmen überein. Ohne dies würden wir 60 verschiedene Stellen in unserem CSS aktualisieren.
Das mag für einige Websites richtig sein und für andere nicht. Das klingt zwar nach einer Ausflucht, aber es stimmt. Vielleicht ist es unrealistisch für eine Website mit viel altem Inhalt. Es könnte brillant sein für eine brandneue Website mit weniger Inhalt, wo es fast genauso viel CSS wie HTML gibt.
Das JavaScript wird letztendlich ein neues Div zu unseren Widgets hinzufügen, das die Aufgabe hat, das Widget zu verdunkeln. Wir nennen diese Klasse „overlay“. Hier ist die CSS dafür
.overlay {
position: absolute; top: 0; left: 0; right: 0; bottom: 0;
background: url(../images/black75.png);
background: rgba(0,0,0,0.6);
text-align: center;
}
Es verwendet RGBa, um für moderne Browser zu verdunkeln (mehr Flexibilität, kann eine HTTP-Anfrage sparen) und fällt auf ein PNG mit Alpha-Transparenz zurück (für IE 7). Eine andere Möglichkeit, damit umzugehen, wäre die Verwendung einer soliden schwarzen Hintergrundfarbe und die Verwendung von normaler Transparenz, aber da in dieser Demo der „Link im mittleren Feld“ im Overlay sein wird und wir nicht möchten, dass dieser ebenfalls transparent ist, funktioniert dies gut.
jQuery JavaScript
Um unser Ziel kurz zu wiederholen: Wenn ein Widget mit der Maus überfahren wird, möchten wir es verdunkeln und einen Link genau in der Mitte platzieren. In unserer Demo haben wir vier Widgets. Einige von ihnen haben unterschiedliche Höhen, daher müssen wir dies berücksichtigen. Jedes Widget zeigt auch unterschiedlichen Text als „mittleren Button-Link“ und eine andere URL an. Das bedeutet, dass ein Teil dieses Codes unterschiedlich sein wird, aber vieles wird gleich bleiben. Das erfordert eine gewisse Abstraktion. In JavaScript könnten wir direkt eine benutzerdefinierte Funktion verwenden, die wir für jedes Widget aufrufen könnten. Im Geiste von jQuery machen wir daraus ein kleines Plugin. Das bedeutet, dass wir einige süße jQuery-spezifische Funktionen wie Chainability intakt halten.
Beachten Sie, dass wir jedem Widget einen eindeutigen Klassennamen hinzugefügt haben. Das dient dazu, Widgets individuell mit diesem Hook in JavaScript ansprechen zu können. Wir hätten auch IDs verwenden können, was etwas effizienter ist, aber hey, Sie haben vielleicht zwei Widgets auf derselben Seite, die denselben Text und denselben Link verwenden. Die Verwendung desselben Klassennamens funktioniert in diesen Umständen, während IDs nicht funktionieren würden. Das ist die gewünschte Abstraktion
$(function() {
$(".widget-one").middleBoxButton("Read More", "#read");
$(".widget-two").middleBoxButton("Go to the Store", "#store");
$(".widget-three").middleBoxButton("Continue", "#more");
$(".widget-four").middleBoxButton("Behold!", "#bazinga");
});
Natürlich ist „middleBoxButton“ keine Funktion. Das werden wir als unser Plugin erstellen. Hier ist das ganze Paket
var $el, $tempDiv, $tempButton, divHeight = 0;
$.fn.middleBoxButton = function(text, url) {
return this.hover(function(e) {
$el = $(this).css("border-color", "white");
divHeight = $el.height() + parseInt($el.css("padding-top")) + parseInt($el.css("padding-bottom"));
$tempDiv = $("<div />", {
"class": "overlay rounded"
});
$tempButton = $("<a />", {
"href": url,
"text": text,
"class": "widget-button rounded",
"css": {
top: (divHeight / 2) - 7 + "px"
}
}).appendTo($tempDiv);
$tempDiv.appendTo($el);
}, function(e) {
$el = $(this).css("border-color", "#999");
$(".overlay").fadeOut("fast", function() {
$(this).remove();
})
});
}
Wenn also ein Widget mit der Maus überfahren wird, wird ein brandneues <div> erstellt. Dieses Div hat die Klassen „overlay“ und „rounded“. Wir wissen bereits, was „rounded“ bedeutet (OOCSS). Wir wissen auch bereits, was das „overlay“ ist; es stellt sicher, dass das Div genauso groß ist wie das Div, indem es absolute Positionierung und die Werte Top, Right, Bottom und Left alle auf Null setzt, und kümmert sich um die Verdunkelung. Mit diesem Div geschieht aber noch nichts.
Dann erstellen wir einen Ankerlink. Wir geben ihm den Text und das href-Attribut, die wir dem Plugin explizit zu diesem Zweck übergeben haben. Dann fügen wir diesen Link zum Overlay-Div hinzu, das wir gerade erstellt haben, und fügen dann beide zusammen zum Widget hinzu. Dieses Geschäft mit der Elementerstellung wird durch die neue Syntax für die Elementerstellung von jQuery 1.4 schön und prägnant. Dieser Teil
$("<a />", {
"href": url,
"text": text,
"class": "widget-button rounded",
"css": {
"top": (divHeight / 2) - 7 + "px"
}
});
Beachten Sie, dass ich alle „Schlüssel“ (der Teil vor dem Doppelpunkt) in Anführungszeichen gesetzt habe. Die meisten Schlüssel funktionieren ohne Anführungszeichen, aber ich hatte Probleme mit dem Schlüssel „class“, der in IE nicht funktionierte. Es stellt sich heraus, dass es kein Fehler ist, sondern dass „class“ ein reserviertes Wort in JavaScript ist, und es ist schlechter Stil, es nicht zu quotieren. Es stellt sich auch heraus, dass es guter Stil ist, alles zu quotieren, wenn man JSON-ähnliche Syntax verwendet, wie diese.
Da eines unserer Ziele hier ist, dass der Link genau in der Mitte erscheint, lassen Sie uns darüber sprechen. Horizontales Zentrieren ist einfach, das Overlay-Div hat text-align: center, also das ist es. Vertikales Zentrieren ist etwas kniffliger. Es gibt CSS-Möglichkeiten dafür, aber keine, die super sauber und einfach sind. Wir verwenden sowieso JavaScript, also nutzen wir das aus. Wir messen einfach die Höhe des Widgets, halbieren sie und schieben den Link um diese Distanz nach unten. Der etwas umständliche Teil ist der Wert „7“. Man hasst es, einen solchen Wert fest zu codieren, wenn ich eigentlich „die halbe Höhe des Buttons“ meine. Das Problem ist, dass ich die Höhe des Buttons nicht berechnen konnte, weil er noch nicht existiert, wenn ich die anderen Attribute setze. Wenn Sie eine Idee haben, lassen Sie es mich wissen. Beachten Sie auch, dass die Höhe des Widgets nicht nur durch die Funktion .height() berechnet wird, sondern durch diese und die obere und untere Polsterung.
Die Callback-Funktion für den Hover (Maus raus) setzt einfach die Umrandungsfarbe auf ihre ursprüngliche Farbe zurück und blendet das Overlay-Div aus (und entfernt es dann). Fertig!
Das ist ein wirklich toller Effekt.
Könnte man nicht outerHeight() für die Höhe des Widgets verwenden?
Ich denke, Sie würden innerHeight() für die Höhe des Widgets verwenden, da outerHeight() die Höhe inklusive Polsterung und Rand ergibt, während innerHeight() die Höhe inklusive Polsterung, aber ohne Rand ergibt.
Entschuldigung, ich hätte klarer sein sollen… outerHeight(false) gibt Höhe + paddingTop + paddingBottom zurück. Der optionale Parameter bestimmt, ob der Rand enthalten ist.
Sie sollten es „Overlay Link“ nennen. Nur meine zwei Cent.
Ich denke, das wäre großartig, um Links über Bildern, Flash-Style, zu legen, wie z. B. einen Play-Button auf einem Bild zu verstecken, der zu einem Video führt, bis der Benutzer mit der Maus darüber fährt.
Wow
Das ist großartig!
Cool
Toller Artikel, aber ich widerspreche dem Begriff objektorientiertes CSS, da es überhaupt nicht objektorientiert ist.
Objektorientiert bedeutet hauptsächlich, sowohl Daten als auch Logik in einer einzigen Einheit, einem Objekt, zu kombinieren. Da Ihr CSS keinerlei Logik enthält, ist es nicht objektorientiert, sondern nur eine einfache Datenstruktur, die Attribute gruppiert, in vielen Programmiersprachen „struct“ genannt.
Es gibt auch keine wirkliche Vererbung, Kapselung oder Polymorphismus hier, da Sie mehrere Klassen auf Ihre Elemente anwenden.
Ich sage das nicht, weil ich gerne Wortspiele mache. Es ist nur so, dass die Verwendung des Begriffs auf diese Weise die Leute verwirren kann.
Schauen Sie sich die Diashow und Erklärung hier an
http://ajaxian.com/archives/nicole-sullivans-object-oriented-css
Dies ist nur ein Mikro-Mikro-Beispiel davon als Ganzes.
Der Begriff ist etwas lächerlich, aber ich habe mich ein wenig damit abgefunden. Ich würde sagen, dass die meisten Leute, die sich mit „echtem“ objektorientiertem Zeug beschäftigen, nicht viel CSS machen. Und Leute, die viel CSS machen, haben nicht viel Erfahrung mit objektorientierter Programmierung, womit diese Definition in Konflikt geraten würde. Fühlen Sie sich frei, mich für diese Klischeebildung anzupingen. =)
Sie verwechseln den Begriff „objektorientiert“ mit „objektorientierte Programmierung“. Etwas kann objektorientiert sein, ohne unbedingt direkt mit dem OOP-Paradigma korreliert zu werden.
Ich nehme es an. Zugegebenermaßen weiß ich nicht viel über all das aus technischer/historischer Sicht. Aber im ganz wörtlichen Sinne ergibt es für mich Sinn. Wir werden uns auf die einzelnen „Objekte“ selbst konzentrieren. Wenn also ein „Objekt“ rund sein möchte, benötigt es einen Klassennamen wie „rounded“. Wenn es 200 Pixel breit sein soll, benötigt es vielleicht einen Klassennamen wie „grid_3“. Wenn es die Eigenschaften eines Nachrichtenblocks übernehmen soll, sollte es die Klasse „news“ haben.
Es ist die Idee, die Styling-Möglichkeiten zurück in das HTML zu bringen. Wenn Sie also einen neuen Inhaltsbereich erstellen, haben Sie diese große Werkzeugkiste zur Verfügung, die sich auf die Eigenschaften des Objekts konzentriert. Anstatt vielleicht mehr CSS schreiben zu müssen, um diesen neuen Inhalt ohne spezifische Hooks unterzubringen.
Objektorientiertes CSS ist ein Missgriff, Ende der Geschichte.
Idealerweise wäre der Weg, mit Ihrem „.rounded“-Dilemma umzugehen, eine CSS-Klasse namens „rounded“ zu haben und dann in der CSS-Datei diese Klasse den semantischen Elementen zuzuordnen, die sie benötigen. Wenn also die Seitenleiste gerundet ist, würden Sie in der CSS-Datei „sidebar“ auf „rounded“ setzen, wo diese Art von Information liegt.
Leider kann man das in CSS nicht tun, also müssen wir uns entscheiden zwischen der Verunreinigung des HTML mit Stilinformationen oder der Wiederholung im CSS.
Chris,
Danke übrigens
.outerHeight() gibt die Höhe inklusive Polsterung und Rand zurück, sowie bei Bedarf den Rand.
Schöner Artikel. Sehr nützlich. Werde es ausprobieren!
Das ist eines der Dinge, die ich auf meiner Liste hatte, um damit zu spielen. Schön, eine Anleitung zum Anfang zu haben! Danke!
Bazinga! :)
Schöner Effekt, Chris.
Genial! Danke Chris! :)
Wie macht man das tastatur- und bildschirmsprachbenutzerfreundlich?
Alles, was Sie tun müssten, ist, denselben Ankerlink, den das Plugin anwendet, in den Text innerhalb des Widgets zu setzen. Tatsächlich könnten Sie das Plugin so ändern, dass es danach sucht, es entfernt und es im Overlay verwendet. Hängt vom Szenario ab…
Bitte machen Sie es so. Und noch etwas: Wenn JS deaktiviert ist, ist der Link auch nicht zugänglich.
Großartige Sachen, Chris!
Chris,
Toller Artikel, wie immer. Sie haben gefragt, ob wir Ideen für die „7“ in der Höhe des Buttons haben könnten. Vielleicht könnten Sie das als Option an die Funktion übergeben. So könnten Sie es für jedes Widget ändern.
Ich denke, sie wären alle gleich, also würde die Übergabe als Parameter die Dinge wahrscheinlich mehr komplizieren als wert sein.
Sehr guter Effekt, danke….
Anthropologie hatte früher diesen Effekt auf ihrer Website, aber anstelle eines schwarzen Hintergrunds und Textes war es ein weißer Hintergrund und ein Bild. Ich kann mich nicht erinnern, ob ihre mittleren Feldlinks ein a:hover-Ereignis hatten – und wenn sie es hatten, muss es subtil gewesen sein, denn es dauerte eine Weile, bis ich erkannte, dass das Klicken auf den eigentlichen Link etwas anderes tat, als nur auf das Bildquadrat selbst zu klicken. Target hat auch etwas Ähnliches, glaube ich. Ich war neugierig, wie es gemacht wurde – gute Arbeit.
Ich habe den Code nur überflogen, also verzeihen Sie mir, wenn ich etwas übersehen habe, aber die Schaltflächen, die erscheinen, sind <a>-Tags, und ihre Anzeigetyp ist Inline, so dass anstatt den richtigen Offset für die Schaltfläche in der Mitte zu berechnen, wäre es nicht einfacher, die Zeilenhöhe des Overlays auf dieselbe Höhe wie seine Höhe zu setzen und den Browser die vertikale Zentrierung erledigen zu lassen? Das würde die Notwendigkeit des hartcodierten „7“ beseitigen, oder?
Ja, das würde funktionieren, außer in dem eher seltenen Fall, dass der Ankerlink zufällig so lang ist, dass er umbricht.
Es ist großartig, OOCSS in Gebrauch zu sehen. Sowohl als Konzept als auch als die eigentlichen Bausteine unter http://wiki.github.com/stubbornella/oocss/ OOCSS war eine echte „magische Kugel“ für alle meine CSS-Projekte. Es glänzt wirklich, wenn es zusammen mit dem Markup-Modell verwendet wird, das von YUI 3 Widgets definiert wird (Sie brauchen YUI dafür überhaupt nicht, es ist nur ein Muster): http://developer.yahoo.com/yui/3/widget/index.html#markup. Fügen Sie eine gut strukturierte Datei hinzu, und CSS wird selbst in sehr großen Projekten äußerst zuverlässig und vorhersehbar.
Ich bin mir nicht sicher, wie Sie die Zeit finden, neue Inhalte zu posten, aber es wird sehr geschätzt.
Ich definiere meine Klassen seit Beginn meiner Arbeit auf diese Weise, mit „rounded“ und dergleichen. Ich finde es viel einfacher, weil Sie Standards für sich selbst über Websites hinweg haben können – es hilft mir, organisiert zu bleiben.
OOCSS = **Cascading** Style Sheets, nichts Neues.
Es scheint das neue „ajax“ (was eigentlich das XMLHttpRequest-Objekt ist) zu sein, aber geben Sie ihm einen schicken Namen und sehen Sie zu, wie es zum neuen großen Ding wird.
Freundliche Bitte – Chris, Kumpel, platziere einen Link zur Demo am Anfang deiner Einträge statt am Ende (oder beides). Ich weiß, es ist klein. Weh mir, ich kann das Scrollrad nicht ein paar Zentimeter nach unten drehen:) Ich weiß. Du stehst jedoch auf meiner täglichen Liste und ich schaue alle paar Tage bei dir vorbei, aber meine Liste ist ziemlich lang. Es gibt sicherlich nicht genug Zeit an jedem Tag, um das Ende der Liste zu erreichen. Wenn also einer deiner Artikel auf den ersten Blick ansprechend aussieht, schaue ich mir normalerweise zuerst die Demo an. So kann ich sie, wenn ich wenig Zeit habe, markieren, später zurückkommen und eine Tiefenanalyse lesen. Nur ein Gedanke.
Ansonsten gute Arbeit. Danke!
Bezüglich der 7: könnten Sie den Anker abseits des Bildschirms erstellen/rendern, dann seine Höhe ermitteln und ihn dann per absoluter Positionierung an den endgültigen Ort verschieben? (Habe es nicht ausprobiert, denke nur laut nach.)
Ich habe eine bessere Idee. Fügen Sie den Link und das Div hinzu, aber mit einer zusätzlichen Klasse, die versteckt ist, wo Sie { display: none; } oder { visibility: hidden; } einfügen (ich glaube, beides würde in diesem Fall funktionieren). Dann existiert Ihr Element. Als nächstes berechnen Sie die Höhe des Links und repositionieren den oberen Rand um minus der Höhe. Dann machen Sie ein schnelles fadeIn und alles sollte in Ordnung sein.
Und bitte machen Sie mir keine Kopfschmerzen, indem Sie mich anschreien, weil ich die <code>-Tags vergessen habe. Es ist früh und meine Kaffeemaschine ist kaputt gegangen. Ich hätte die Tags korrigiert, wenn ich meinen Kommentar hätte bearbeiten können.
Das mag Gerede von meiner Seite sein: Sollten Sie nicht in Betracht ziehen, die URL aus dem Widget-Div zu holen? Das natürlich als Zusatzservice für den Fall, dass keine URL angegeben wurde. Ich denke, das wäre eine großartige Ergänzung zu dem, was Sie über verschiedene Umstände und die mögliche Aufnahme der URL im Text für die Degradation erwähnt haben (wäre auch nicht schlecht für Ihr SEO).
Auf jeden Fall: Tolle Arbeit auf deinem Blog und mach weiter so. Ich freue mich auch auf deinen nächsten Screencast!
Mist. Könnten Sie bitte etwas gegen meine Fehler in den vorherigen Kommentaren tun? Hauptsächlich geschätzt (a)
Sieht alles sehr gut aus.
Ein Vorschlag jedoch. Halten Sie die Randfarbe aus dem Widget heraus und fügen Sie stattdessen eine CSS-Klasse hinzu/entfernen Sie sie, anstatt eine CSS-Randfarbe anzuwenden.
z. B. addClass(“jquery-middleboxlinks-hover”);
Hallo,
Ich mag, was ich sehe, es ist eine schöne Demo
Nebenbemerkung: zum Randradius, den Sie in der Demo verwenden, weiß ich, dass die Demo ohne funktioniert, und ich weiß, dass Sie gerne Border-Radius verwenden, ich sehe es in vielen Ihrer Projekte
aber es funktioniert immer noch nicht in IE, und da ich für Kunden arbeite, die Design X verlangen und somit Design X erhalten sollten, und nicht einen anderen Browser verwenden sollten, um Design X zu sehen, mag ich Border-Radius (noch) nicht.
Das ist ein wirklich cooler Effekt, danke fürs Teilen!
Nicht so einfach für mich bis zu diesen Beispielen, es war eine schwierige Aufgabe, mittlere Felder zu haben und trotzdem ein leicht zu bearbeitendes Layout beizubehalten… gute Arbeit