Responsive Images sind in den letzten Jahren in aller Munde seit es Smartphones & Tablets gibt. Die Problematik besteht darin, dass es statt einem Bild für alle Gerätetypen, – welches meistens dazu führt, dass man unnötig große Dateien herunterladen muss – speziell für die entsprechenden Geräte bzw. Bildschirmgröße Bilder bereitstellt.

Seit geraumer Zeit nimmt die Unterstützung der Browser für Responsive Images zu.

Ein kleines Beispiel als Grundlagen anhand meines letzten Urlaubs

Der Clou bestehet darin, dass das Img-Tag ein neues Attribut „srcset“ bekommt. Dies ist ein Satz von kommaseparierten Bildern. Jedes Bild bekommt einen sogenannten Descriptor, der die Breite (w) des Bildes definiert, damit der Browser die richtige auswählen kann. Im obigen Beispiel sind es bei „Buyukada_Small.jpg“ 350w etc.

Zusätzlich kann man optional ein „sizes“ Attribut definieren. Diese hat den Zweck dem Browser mitzuteilen wie Breit das Bild dargestellt werden soll im aktuellen Viewport. Die Einheit lautet „vw“ (viewport-width). 100vw wären demnach 100% der Viewportbreite. Der Browser geht implizit bei fehlendem sizes von 100vw aus.

Im Beispiel ist eine Kombination (auch optional) mit einem MediaQuery bei mindestens 600px Breite ein vw von 50 angegeben.

Das bedeutet, dass das Bild auf allen Geräten, die einen Viewport von mindestens 600px haben nur 50% breit dargestellt wird,

bei kleiner 600px in voller Viewportbreite.

min-width:600px 50vw

 

 

 

 

 

 

 

100vw

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Die Breite des Bildes beinhaltet auch schon die „Density“ also Dichte.

Bei hochauflösenden Bildschirmen wie z.B. dem Retina-Display ist dies auch nötig wegen sichtbaren Qualitätsverlusten. Die hohen Auflösungen erfordern ebenfalls höhere aufgelöste Bilder.

Die Syntax ist ähnlich. Das „sizes“ Attribut ist unnötig

Mein Ziel ist es einen Html Helper in ASP.NET MVC zu erstellen, der mir die Erstellung von Responsive Images erleichtert. Vorzugsweise als Fluent Api und für beide Descriptorarten, d.h Width und Density. Ein leeres MVC-Projekt reicht aus.

Es bietet sich an eine abstracte Basis-Klasse „BaseResponsiveImage“ zu erstellen mit den Eigenschaften für Bildpfad (ImageSrc),Bildtext (ImageAltText) und Srcset-Dictionary (ImageSrcset)

Danach wäre es angebracht ein generisches Interface mit einer Methode zum Hinzufügen von einem Bild zum Srcset („AddImageToSrcset“) zu erstellen. Zusätzlich wird IHtmlString implementiert für den späteren Html-Output

Danach geht es an die konkrete Implementierung der Descriptor Klassen. Fangen wir mit dem Density an. Dafür eine Klasse „ResponsiveImageWithDensityDescriptor“ anlegen.

Da die Klasse  „IResponsiveImage“ implementiert muss sie „ToHtmlString()“ mit Leben füllen. Es wird ein image-Tag mit Hilfe des  TagBuilders erstellt. VirtualPathUtility sorgt dafür dass der Bildpfad korrekt aufgelöst wird (bei „~/Content/…). Ansonsten kann man die Tilde nicht benutzen. Daraufhin werden eventuell vorhandene Srcset-Einträge kommasepariert zusammengebaut und dem „srcset“-Attribut zugewiesen.

In ähnlicher Weise wird die Klasse für den Width-Descriptor gebaut. Mit dem Unterschied das die Klasse eine „sizes„-Eigenschaft braucht.

Hierfür kann man eine separate Klasse anlegen

Die Enumerationen

Welche somit in der Klasse „ResponsiveImageWithWidthDescriptor“ eingesetzt werden

Die AddSizesAttribute-Methode fängt die optionalen Fälle der Viewport-Breite mit und ohne MediaQuerys ab.

Unserem Ziel näherkommend noch eine HtmlHelper

Die generische Methode deckt beide Fälle ab (auf Validierung der Parameter habe ich verzichtet) und erstellt je nach Bedarf eine Instanz der gewünschten Descriptor-Klasse.

Somit kommt schlussendlich die Anwendung

Der Vorteil der Fluent Api besteht darin, dass man mit der Methoden-Verkettung sehr flexibel ist. Übrigens die Klammern beim Html-Helper braucht man, weil ansonsten Razor den generischen Typ als Html interpretiert und somit eine Fehlermeldung geworfen wird.

Alternativ hätte man auch zwei HtmlHelper erstellen können um dies zu verhindern.

Das Projekt ist hier in Github verfügbar