Schlagwort: CSS

Ordnung ist das halbe Leben…

06. Juli 2011

Ordnung ist das halbe Leben
Geschachtelte geordnete Listen mit einer fortlaufenden Nummerierung in Form von 1., 1.1, 1.1.1 usw.? Seit CSS 2 lassen sich dank der neuen CSS-Counter auch solche Arten der Aufzählung realisieren. Für ältere Browser wie dem Internet Explorer 7 müssen dabei allerdings ein paar Hürden genommen werden. Dabei sind die CSS-Counter nicht auf Listenelemente beschränkt, da gäbe es eine ganze Reihe schöner Einsatzszenarien. Wahrlich kein brandneues Thema mehr, aber ein Blick lohnt trotzdem.

Geordnete Listen

CSS-Counter erlauben das Zählen von Instanzen bestimmter Elemente bzw. Selektoren. In Kombination mit den Pseudo-Elementen :before und :after lassen sich dann ganze neue Formen der Nummerierung erstellen. Die CSS-Counter sind dabei deutlich leistungsstärker als das alte HTML start Attribut, das ohnehin als deprecated gilt, und ausschließlich die Nummerierung einer Ebene bzw. eines Listenelementes beeinflusst.
Die Nummerierung mit Hilfe von CSS basiert setzt sich aus mehreren Eigenschaften und Funktionen zusammen:

  • counter-reset: Setzt einen oder mehrere Zähler zurück, ein Zähler ist dabei eine frei wählbare Variable. Optional lässt sich für jeden Zähler noch ein Anfangswert festlegen, der Standardwert ist 1.
  • counter-increment: Zählt einen oder mehrere Zähler hoch, auch hier kann man über einen zweiten optionalen integeren Wert die Zählweise beeinflussen (selbst negative Werte sind erlaubt).
  • content: Gibt mit Hilfe der Funktionen counter() oder counters() die Nummerierung aus.

Ein Beispiel

OL {
  counter-reset: item;
}
OL LI {
  display: block;
}
 
OL LI:before {
  content: counter(item) ". ";
  counter-increment: item;
}

Betrachtet man dieses erste Beispiel im Browser, so sieht das Ergebnis noch nicht anders aus, als eine ganz normale geordnete Liste (OL), der einzige Vorteil liegt darin, dass sich die Nummerierung nun erheblich besser gestalten lässt, ohne dass man weitere Tag Verschachtelungen vornehmen muss. Auf einen Nachteil sei an dieser Stelle auch gleich hingewiesen. In Sachen “Accessability” sind diese Lösungen negativ zu bewerten, denn über CSS generierter Content manipuliert die DOM nicht (siehe hier), so dass aktuelle Screen-Reader diese Informationen schlicht nicht ausgeben, die Liste hätte also keine Nummerierung mehr.
Für eine fortlaufende Nummerierung, die die übergeordneten Nummern übernimmt, kann man den CSS Code wie folgt verändern:

OL {
  counter-reset: item;
}
OL LI {
  display: block;
}
 
OL LI:before {
  content: counters(item, ".") ".";
  counter-increment: item;
}

Nun werden die Nummern der übergeordneten Listenelemente übernommen. Die Funktion counters() liefert im Gegensatz zu counter alle Instanzen eines Zählers gleichzeitig. Der zweite Parameter ist das Trennzeichen, mit dem diese Instanzen verkettet werden. Doch Vorsicht mit dieser Syntax. Sie führt im Internet Explorer 7 dazu, dass alle folgenden CSS Notationen nicht mehr interpretiert werden, selbst wenn diese in separaten Stylesheet Dateien abgelegt sind. Anscheinend bringt die Notation der Anfürhrungszeichen innerhalb der Klammern den CSS Interpreter völlig durcheinander. Bedeutet, man kann wahlweise sicher stellen, dass der entsprechende Code projektweit wirklich immer an letzter Stelle kommt, oder man nutzt die Funktion counter anstatt counters – wobei diese Lösung den CSS-Code abhängig von der möglichen Verschachtelungstiefe deutlich vergrößern kann:

/* 1. Ebene */
BODY OL {
  counter-reset: level1;
  list-style-type: none;
}
 
OL LI:before {
  content: counter(level1) ". ";
  counter-increment: level1;
}
 
/* 2. Ebene */
OL LI OL {
  counter-reset: level2;
}
 
OL LI OL LI:before {
  content: counter(level1) "." counter(level2) " ";
  counter-increment: level2;
}
 
/* 3. Ebene */
OL LI OL LI OL {
  counter-reset: level3;
}
 
OL LI OL LI OL LI:before {
  content: counter(level1) "." counter(level2) "." counter(level3) " ";
  counter-increment: level3;
}
...

CSS basiertes text-overflow in allen Browsern

17. Juni 2010

Pur CSS textoverflow in allen Browsern
Nochmal ein Beitrag zum Thema Textbegrenzung. Längere Texte abzuschneiden, weil sie anderenfalls bestimmte Rahmengrößen brechen würden, ist eine immer wiederkehrende Anforderung. Solche Kürzungen kann man zum Teil serverseitig erledigen – aber das ist nicht unter allen Umständen sinnvoll. Schwierig wird es immer dann, wenn diese Kürzung nicht auf einer definierten Zeichenlänge basiert, sondern auf einer definierten Größe (bspw. innerhalb einer Tabelle, oder einer Schaltfläche). Der Internet Explorer kennt die CSS-Eigenschaft text-overflow, eine entsprechende Implementierung im Firefox fehlt. Es geht trotzdem…

In meinem Artikel Text begrenzen, aber richtig hatte ich einige serverseitige Lösungen zum Begrenzen von Text vorgestellt. Solche Ansätze scheitern, wenn es bei der Begrenzung gar nicht um die Anzahl von Zeichen geht, sondern layoutabhängig sind. Die naheliegende Verwendung der CSS-Eigenschaft text-overflow wäre ideal, hier wird der Text nicht nur abgeschnitten, sondern in der Form Dieser Text geht noch weiter … dargestellt:

Beispielcode – die HTML Syntax

<div class="fixed-box">
  <p class="truncate">Ein viel zu langer Text für das Elternelement.</p>
</div>

Legt man folgenden CSS Code zugrunde, dann wird der Text zwar in allen Browsern “abgeschnitten” (durch overflow:hidden), aber nur im Internet Explorer und im Webkit (Safari, Chrome) greift text-overflow mit der Ausprägung ellipsis:

.fixed-box {
  width:100px;
}
 
.truncate {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

Aber wie hilft man Firefox auf die Sprünge? Sicher – man könnte sich über JavaScript helfen, bei Ajaxian wird auf bspw. ein entsprechendes JQuery Plugin verwiesen. Es gibt aber noch eine Alternative und die basiert auf XBL. XBL (XML Binding Language) ist eine XML-basierte Auszeichnungssprache, mit der man das Verhalten und Aussehen von XML- und HTML-Elementen beschreiben kann. Dies geschieht über sogenannte Bindings (Bindungen) in XBL, die an ein solches Element angehängt werden. Die Bindings werden in einer separaten XBL-Datei definiert. Über ein Binding kann auch Text in das XML- oder HTML-Element eingefügt werden. Ein Binding kann an mehrere unterschiedliche Elemente angehängt werden. Der Code für die Implentierung von text-overflow ellipsis:

<?xml version="1.0"?>
<bindings
  xmlns="http://www.mozilla.org/xbl"
  xmlns:xbl="http://www.mozilla.org/xbl"
  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
  <binding id="ellipsis">
    <content>
      <xul:window>
        <xul:description crop="end" xbl:inherits="value=xbl:text">
          <children/>
        </xul:description>
     </xul:window>
    </content>
  </binding>
</bindings>

Cross Browser text-overflow CSS Syntax

Die XML Syntax wird als Datei abgespeichert und dann über CSS referenziert:

.truncate {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  /* Firefox mit text-overflow */
  -moz-binding: url(ellipsis.xml#ellipsis);
  /* und nun auch noch Opera */
  -o-text-overflow:ellipsis;
}

Einen kleinen Schönheitsfehler hat die Sache im Firefox Version 3.6. Aufgrund eines Bugs bei -moz-binding werden einmal gesetzte Werte nicht wieder geändert. Heißt bei Fluid-Designs bleibt der “ellipsis” Effekt auch dann noch vorhanden, wenn er eigentlich nicht mehr benötigt wird.

Habe heute ein wenig mit der Syntax herumgespielt und dabei festgestellt, dass die genannte XML Fassung für Textflow im Firefox 3.6.3 einen Bug hat. Sobald der Text, der gekürzt werden soll, inline-Elemente wie bspw. STRONG oder EM enthält, “verschwinden” diese Fragmente. Eine modifizierte Fassung des XML-Codes schafft Abhilfe:

<?xml version="1.0"?>
<bindings
  xmlns="http://www.mozilla.org/xbl"
  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<binding id="none">
  <content><children/></content>
</binding>
<binding id="ellipsis">
  <content>
    <xul:label crop="end"><children/></xul:label>
  </content>
  <implementation>
    <field name="label"> document.getAnonymousNodes( this )[ 0 ] </field>
    <field name="style"> this.label.style </field>
    <property name="display">
       <getter>
         this.style.display
       </getter>
       <setter>
         if( this.style.display != val ) this.style.display= val
       </setter>
    </property>
    <property name="value">
      <getter>
         this.label.value
      </getter>
      <setter>
        if( this.label.value != val ) this.label.value= val
      </setter>
    </property>
    <method name="update">
      <body>
         var strings= this.textContent.split( /\s+/g )
         if( !strings[ 0 ] ) strings.shift()
         if( !strings[ strings.length - 1 ] ) strings.pop()
         this.value= strings.join( ' ' )
         this.display= strings.length ? '' : 'none'
      </body>
    </method>
    <constructor> this.update() </constructor>
  </implementation>
  <handlers>
    <handler event="DOMSubtreeModified"> this.update() </handler>
  </handlers>
</binding>
</bindings>

Dafür ist der erwähnte Bug bei dynamisch modifizierten Elementen (sei es über Javascript oder flexibel skalierbare Boxen) nicht mehr aktuell und kann gestrichen werden (wurde gestrichen). Hier sind noch einmal alle Tests zusammgefasst zu finden.

Seite 1 von 3123