HTML5-Tutorium: JavaScript: Hello World 06: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Keine Bearbeitungszusammenfassung
 
(57 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
{{In Bearbeitung}}
{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}
{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}


'''Musterlösung''': [https://glossar.hs-augsburg.de/beispiel/tutorium/es5/hello_world/WK_HelloWorld05/web/index.html <code>index.html</code>],
'''Musterlösung'''<br/>
[([https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld05/ SVN-Repository])
v01: [https://glossar.hs-augsburg.de/beispiel/tutorium/2024/wk_hello_world/wk_hello_world_06/web_v01/index.html <code>index.html</code>] ([https://validator.nu/?doc=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2024%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb_v01%2Findex.html HTML validate])<br/>
v02: [https://glossar.hs-augsburg.de/beispiel/tutorium/2024/wk_hello_world/wk_hello_world_06/web_v02/index.html <code>index.html</code>] ([https://validator.nu/?doc=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2024%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb_v02%2Findex.html HTML validate]; Modularisierung analog zu [[HTML5-Tutorium: JavaScript: Hello World 04|Hello World 04]] v02)<br/>
v03: [https://glossar.hs-augsburg.de/beispiel/tutorium/2024/wk_hello_world/wk_hello_world_06/web_v03/index.html <code>index.html</code>] ([https://validator.nu/?doc=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2024%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb_v03%2Findex.html HTML validate]; Konfiguration mittels JSON analog zu [[HTML5-Tutorium: JavaScript: Hello World 04|Hello World 04]] v03)<br/>
[{{Git-Server}}/kowa/wk_hello_world_06.git Git-Repository]
 
==Anwendungsfälle (Use Cases)==
==Anwendungsfälle (Use Cases)==
Gegenüber dem [[HTML5-Tutorium:_JavaScript:_Hello_World_04|vierten Teil des Tutoriums]]
Gegenüber dem [[HTML5-Tutorium:_JavaScript:_Hello_World_05|dritten, vierten und fünften Teil des Tutoriums]]
ändern sich die die Anwendungsfälle nur geringfügigDas Begrüßungsformular soll ''zweimal''
ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
im Browser angezeigt werden, einmal auf Deutsch und auf Englisch. Beide Begrüungsformulare sollen
 
unabhängig voneinander funktionieren.
In diesem Teil des Tutoriums geht es darum, CSS durch SCSS zu ersetzen, um den CSS-Code „[[DRY]] zu machen“.
 
== Erstellen eines neuen Projekts ==
 
Erstellen Sie ein neues Projekt <code>hello_world_06</code> als Fork von <code>hello_world_05</code>.
 
==SCSS==
 
Anstelle von CSS-Dateien verwenden Sie künftig SCSS-Dateien. Das ist zunächst einmal nicht weiter schwer,
das jede CSS-Datei automatisch auch eine SCSS-Datei ist. Bei der Verwendung von CSS können Sie
allerdings das Prinzip „[[Don't repeat yourself]]“ (DRY) nicht beachten. Sie müssen für verschiedene Elemente
ständig Informationen wiederholen (gewünschter Font, Hintergrundfarbe, Größenangaben etc.). Deshalb
gibt es mehrere Projekte wie {{zB}} [[LESS]], [[Sass]]/SCSS, [[Stylus]], die den CSS-Standard erweitern, um dieses Problem
zu vermeiden. Sass verwendet allerdings eine ganz andere Syntax als CSS. Allerdings
unterstützt das Sass-Projekt auch die Sprache SCSS, die CSS einfach um weitere syntaktische Elemente ergänzt.  
Zum Beispiel kann man in SCSS Konstanten definieren:
 
<source lang="CSS">
$font-family-serif: "Times New Roman", Times, serif;
</source>


Ein Grundprinzip der Programmierung lautet [[Don't repeat yourself]] (DRY).  Sie könnten nun einfach den vorhandenen
Und nun kann man in eine SCSS-Datei anstelle von <code>"Times New Roman", Times, serif</code> stets <code>$font-family-serif</code>
Code duplizieren und entsprechend anpassen. Aber genau das würde gegen das Prinzip „Keep your code DRY“ verstoßen.
schreiben, um den Font von bestimmten Elementen zu definieren.  
Code-Duplikation kann mit Hilfe von [[Klasse (objektorientert)|Klassen]] vermieden werden. Sie stellen eine Art
„Blaupause“ dar, um Objekte mit ähnlichen Eigenschaften ganz einfach erstellen zu können.


==Erstellen eines neuen Projektes==
<source lang="CSS">
p
{ font-family: $font-family-serif; }


Erzeugen Sie wie im  [[HTML5-Tutorium:_JavaScript:_Hello_World_04|vierten Teil des Tutoriums]] ein neues Projekt,
label
diesmal allerdings mit dem schönen Namen <code>HelloWorld05</code>“ und speichern Sie dieses wieder
{ font-family: $font-family-serif; }
in Ihrem SVN-Repository (Achtung: <code>node_modules</code> muss existieren und auf der Ignore-Liste stehen). 
</source>


Kopieren Sie nun aus Ihrer Lösung des vierten Teil des Tutoriums die Ordner <code>src</code> und <code>web</code>
Wenn man nun diesen Font ändern will,
(jeweils samt allen darin enthaltenen Ordnern und Dateien) sowie die Dateien <code>gruntfile.js</code>,
muss das nicht mehr bei allen Elementen einzeln passieren. Es reicht, die Konstantendefinition abzuändern.
<code>package.json</code>, <code>package-lock.json</code> und <code>webpack.config.js</code>
Der SCSS-Code ist nun DRY.
fügen Sie sie ins Wurzelverzeichnis des fünften Teils ein.  


Weisen Sie WebStorm wiederum an, die Inhalte der Ordner <code>node_modules</code> und <code>web/js</code>
==== Weiterentwicklung von CSS ====
nicht auf Syntaxfehler zu überprüfen. Gegebenenfalls müssen Sie auch wieder die Dateien <code>gruntfile.js</code>
... <code>webpack.config.js</code> unter die Versionsverwaltung von SVN stellen (<code>Add to VCS</code>).


Ändern Sie in den Dateien <code>package.json</code> und <code>web/index.html</code> die Versionsnummern,
CSS entwickelt sich stetig weiter. Seit einiger Zeit werden auch hier Variablen unterstützt:
die Beschreibung und gegebenenfalls den Pfad zum Repository Ihres Projektes.


Zu guter Letzt öffnen Sie das WebStorm-Terminal und führen den Befehl <code>npm install</code>aus.
<source lang="CSS">
Damit werden dieselben Node.js-Pakete installiert wie im vierten Teil des Tutoriums.
:root
{ --font-family-serif: "Times New Roman", Times, serif; }


Löschen Sie die Datei <code>web/js/app.bundle.js</code> und
p
rufen Sie anschließend <code>grunt</code> auf, um diese Datei erneut zu erzeugen.
{ font-family: var(--font-family-serif); }
Wenn Sie jetzt die Datei <code>index.html</code> im Browser öffnen, sollte die
 
Web-Anwendung so wie in Teil 4 der Aufgabe funktionieren.
label
{ font-family: var(--font-family-serif); }
</source>
 
Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: <code>math</code>, CSS: <code>calc</code>).
Das heißt, die Bedeutung von SCSS, Less etc. schwindet. Aber zurzeit bieten sie immer noch genügend mächtige Erweiterungen gegenüber CSS,
wie {{zB}} die Möglichkeit, CSS-Elemente zu verschachteln, sodass sich der Einsatz von SCSS noch lohnt.
 
==== Transformation von SCSS in CSS ====
 
Leider unterstützt kein Browser SCSS direkt (im Gegensatz zu CSS). Aber für was gibt es Transpiler, die eine SCSS-Datei
automatisch in eine CSS-Datei übersetzen können. Vite unterstützt CSS-Transpiler von Haus aus. Man muss den gewünschten Transpiler lediglich installieren:


==Verfeinerung der Webpack-Umgebung==
Zunächst benötigen Sie ein paar weitere Node.js-Module
<source lang="bash">
<source lang="bash">
npm install --save-dev es6-autobind
npm i -D sass
npm install --save-dev node-sass sass-loader
</source>
npm install --save-dev extract-text-webpack-plugin optimize-css-assets-webpack-plugin
 
Benennen Sie die Datei <code>src/css/body.css</code> in <code>src/css/body.scss</code> um. Ersetzen Sie außerdem
in der Datei <code>src/js/main.js</code> den Import-Befehl
 
<source lang="javascript">
import '/css/body.css';
</source>
</source>


Das Modul <code>es6-autobind</code> wird im Zusammenhang mit der Definition der Klasse <code>Greet</code>
durch
benötigt . Daher wird es erst später besprochen.


Im vierten Teil des Tutoriums wurde die Datei <code>initial.css</code> nicht von webpack verwaltet,
<source lang="javascript">
sondern direkt in das Verzeichnis <code>web/css</code> eingefügt. Damit liegt auch die
import '/css/body.scss';
Verantwortung für die Komprimierung dieser Datei beim Programmierer. Das soll sich ändern.
</source>
Sie erweitern die Webpack-Konfiguration so, dass künftig auch diese Datei unter der Kontrolle
von webpack steht.


===SCSS===
Wenn Sie Ihren Code nun mittels <code>npm run dev</code> laufen lassen oder mittels <code>npm run build</code> übersetzen,
sollte die Anwendung noch funktionieren, da der SASS-Loader die neue SCCS-Datei in geeigneten CSS-Code übersetzt.


Anstelle von CSS-Dateien verwenden Sie künftig SCSS-Dateien. Das ist zunächst einmal nicht weiter schwer,
Schwieriger ist der direkte Import von <code>head.scss</code> in der Datei <code>index.html</code>,  
das jede CSS-Datei automatisch auch eine SCSS-Datei ist. Bei der Verwendung von CSS können Sie
da diese SCSS-Datei von Vite nicht in CSS transformiert wird. Ein Workaround für dieses Problem wird später vorgestellt.
allerdings das Prinzip  „[[Don't repeat yourself]]“ (DRY) nicht beachten. Sie müssen für verschiedene Elemente
ständig Informationen wiederholen (gewünschter Font, Hintergrundfarbe, Größenangaben etc.). Deshalb
gibt es mehrere Projekte wie {{zB}} [[LESS]] und [[Sass]] , die den CSS-Standard erweitern, um dieses Problem
zu vermeiden. Sass verwendet allerdings eine ganz andere Syntax als CSS. Allerdings
unterstützt das Sass-Projekt auch die Sprache SCSS, die CSS einfach um weitere syntaktische Elemente ergänzt.
Zum Beispiel kann man in SCSS Konstanten definieren:


<source lang="CSS">
===Vite-Konfiguration===
$background-color:  #C5EFFC;
</source>


Und nun kann man in der CSS-Datei anstelle von  <code>#C5EFFC</code> stets  <code>&#36;background-color</code>
Fügen Sie <code>"config"</code> als Abkürzung für <code>"./src/css/_config.scss"</code> in die Datei <code>vite.config.js</code> ein.
schreiben, um die Hintergrundfarbe von bestimmten Elementen zu definieren. Wenn man nun dieses Farbe ändern will,
muss das nicht mehr bei allen Elementen einzeln passieren. Es reicht, die Farbe in der Konstantendefinition abzuändern.
Der CSS-Code ist nun DRY.


Leider unterstützt kein Browser SCSS direkt. Aber für was gibt es Transpiler wie webpack, die eine SCSS-Datei
<source lang="javascript">
automatisch in eine CSS-Datei übersetzen können.
...
  resolve:
  { alias:
    { ...
      'config': fileURLToPath(new URL('./src/css/_config.scss', import.meta.url)),
      ...
    }
  }
...
</source>


Ersetzen Sie in Ihrem Projekt die Datei <code>src/css/main.css</code> durch
===SCSS-Konfiguration===
drei SCSS-Dateien: <code>_config,scss</code>, <code>initial.scss</code> und </code>app.scss</code>.


In der Datei <code>_config,scss</code> werden alle von den anderen SCSS-Dateien benötigten Konstanten definiert.
In der Datei <code>_config.scss</code> werden alle von den anderen SCSS-Dateien benötigten Konstanten definiert.
Das heißt, das DRY-Prinzip „Konstanten gehören nicht in den Code, sondern in Konfigurationsdateien“ wird ab sofort beachtet.
Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will,  
Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will,  
reicht es die entsprechenden Konstanten anzupassen und schon erzeugt webpack automatisch aktualisiere
reicht es, die entsprechenden Konstanten anzupassen und schon erzeugt Vite automatisch aktualisiere
CSS-Dateien.
CSS-Dateien.


Die Datei <code>initial.scss</code> enthält möglichst wenig Code. Das ist Vorlage für die Datei <code>initial.bundle.css</code>,
Der Underscore <code>_</code> am Beginn des Dateinamens deutet an, dass diese SCSS-Datei nur von anderen SCSS-Dateien
die im HTML-Head-Bereich geladen vor dem Body-Inhalt werden soll.
aber nicht von HTML- oder JavaScript-Dateien importiert werden. Durch SCSS-Import-Befehle ist es möglich, auch SCSS-Dateien
Die eigentlichen CSS-Informationen der Web-Anwendung werden in <code>app.scss</code> gespeichert. Die zugehörigen
zu modularisieren.
CSS-Anweisungen werden von webpack wie gehabt in <code>app.bundle.js</code> integriert.


'''<code>src/css/_config,scss</code>'''
'''<code>src/css/_config.scss</code>'''
<source lang="CSS">
<source lang="CSS">
@use 'sass:math';
$background-color:  #C5EFFC;
$font-family-sans:  Verdana, Helvetica, sans-serif;
$font-family-sans:  Verdana, Helvetica, sans-serif;
$font-family-serif: "Times New Roman", Times, serif;
$font-family-serif: "Times New Roman", Times, serif;
$background-color#C5EFFC;
 
$font-size-base:    3vw;
$font-size-factor:  1.25;  /* cmp. https://type-scale.com/ */
   
$font-size-h5:      math.pow($font-size-factor,1)*$font-size-base;
$font-size-h4:      math.pow($font-size-factor,2)*$font-size-base;
$font-size-h3:      math.pow($font-size-factor,3)*$font-size-base;
$font-size-h2:      math.pow($font-size-factor,4)*$font-size-base;
$font-size-h1:      math.pow($font-size-factor,5)*$font-size-base;
 
$font-size-p:      math.pow($font-size-factor,0)*$font-size-base;
$font-size-p-large: math.pow($font-size-factor,2)*$font-size-base;
 
$font-size-small:  math.pow($font-size-factor,-1)*$font-size-base;
</source>
</source>
In dieser SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:


Diese Datei kann nun mit Hilfe des SCSS-Befehls <code>@import</code>  
* Mathematische Berechnungen: <code>@use 'sass:math';</code>
in die anderen beiden  SCSS-Dateien eingefügt werden. Webpack (genauer gesagt das SASS-Modul von webpack)
* Definition von Konstanten (die teilweise per Berechnung ermittelt werden)
kennt diesen Befehl und führt im beim Erstellen der zugehörigen CSS-Dateien auch aus.
* Fonts sollten aus designerischen Gründen besser lokal gespeichert und per CSS eingebunden werden.


Der Import-Befehl ist hier notwendig, da in der Datei <code>initial.scss</code> die Konstante <code>&#36;background-color</code>
Konstanten starten in SCSS mit einem Dollarzeichen. Sobald eine Konstante definiert wurde,
verwendet wird. Ansonsten enthält dies Datei nur den schon bekannten CSS-Code.
kann sie in allen weiteren SCSS-Konstrukten verwendet werden. In SCSS stehen einen Operatoren zur Verfügung wie
<code>+</code>, <code>-</code>, <code>*</code> und <code>/</code>, um Maße zu berechnen. Es gibt
weitere Operatoren zum Vergleichen von Zahlen und Maßen sowie zur Berechnung von Strings und booleschen Werten:
https://sass-lang.com/documentation/operators.<ref>https://sass-lang.com/documentation/operators</ref>


'''<code>src/css/initial.scss</code>'''
Die Datei <code>_config.scss</code> kann nun mit Hilfe des SCSS-Befehls <code>@import 'config';</code> (ohne Underscore und ohne Endung, wegen der zuvor eingeführten Vite-Aliase)
in die anderen beiden SCSS-Dateien eingefügt werden. Das Sass-Package
kennt diesen Befehl und führt ihn beim Erstellen der zugehörigen CSS-Dateien auch aus.
 
Der Import-Befehl hat erst dann einen Effekt, wenn in den anderen Dateien auf diese Konstanten zugegriffen wird.
Aber er schadet auch nicht, wenn auf keine der dort definierten Konstanten zugegriffen wird. Der Import-Befehl selbst
taucht ebenso wenig in den generierten CSS-Dateien auf, wie die Konstantendefinitionen. Der Transpiler ersetzt Konstanten
in CSS-Definitionen durch ihren jeweiligen Wert.
 
Sie können nun beispielsweise in der Datei <code>head.scss</code> die Konstante <code>&#36;background-color</code>
verwenden. In der daraus erzeugten CSS-Datei steht weiterhin der Farbwert <code>#C5EFFC</code>;
 
'''<code>src/css/head.scss</code>'''
<source lang="CSS">
<source lang="CSS">
@import 'config';
@import 'config';


body
body
{ background-color: $background-color;
{ background-color: $background-color; }
}


.hidden
.hidden
{ display: none;
{ display: none; }
}
</source>
</source>


Die Datei <code>app.scss</code> ist deutlich umfangreicher. Daher soll der zugehörige CSS-Code
Die Datei <code>body.scss</code> ist deutlich umfangreicher. Daher wird der zugehörige CSS-Code
ja auch erst gemeinsam mit der Datei <code>app.bundle.js</code> geladen werden. Das meiste ist üblicher
ja auch erst dynamisch gemeinsam mit der Datei <code>web/js/main.js</code> geladen.  
CSS-Code, den Sie schon im vierten Teil des Tutoriums kennengelernt haben. Es gibt ein paar neue
Elemente, wie die CSS-Klassen-Elemente <code>.left</code> und <code>.right</code>, die in der HTML-Datei dieses
Tutoriums zusätzlich verwendet werden. Außerdem sehen Sie in der Datei noch ein  paar weitere SCSS-Elemente. Diese werden
im Anschluss an den folgenden code beschrieben.


'''<code>src/css/app.scss</code>'''
'''<code>src/css/body.scss</code>'''
<source lang="CSS">
<source lang="CSS">
@import 'config';
@import 'config';
html, body
{ height:          100%;
  font-size:        2vw !important;
  font-family:      $font-family-sans;
  background-color: $background-color;
}


html
html
{ display: table;
{ height: 100%;
   width:  100%;
   width:  100%;
  display: table;
}
}


Zeile 148: Zeile 197:
   text-align:      center;
   text-align:      center;
   vertical-align:  middle;
   vertical-align:  middle;
  background-color: $background-color;
  font-size:        $font-size-base !important;
  font-family:      $font-family-sans;
}
}


h1
h1
{ padding-bottom: 0;
{ padding:   0;
   margin-bottom: 0;
   margin:   0;
}
   font-size: $font-size-h1;
 
#section_form
{ text-align:   center;
  width:        21em;
  margin-left: auto;
  margin-right: auto;
 
  h1
  { font-size:    200%;
    margin-bottom: 0.5ex;
  }
}
 
#section_hello
{ h1
  { font-size: 270%;
  }
}
}


p, label
p, label
{ font-family: $font-family-serif;
{ font-family: $font-family-serif;
   font-size:  100%;
   font-size:  $font-size-p !important;
}
}


label, input, button
label, input, button
{ width:         10em;
{ width:     10em;
   font-size:     100%;
   font-size: 100%;
   display:       inline-block;
   display:   inline-block;
   box-sizing:   border-box;
   box-sizing: border-box;
   margin-bottom: 0.5ex;
   margin:     0.5ex;
}
}


Zeile 190: Zeile 225:
}
}


@mixin panel()
#section_form
{ padding: 0;
{ text-align:   center;
   width50%;
  margin-left:  auto;
   margin-right: auto;
 
  h1
   { margin-bottom: 0.5ex; }
}
}


.left
#section_hello
{ float: left;
{ p
   @include panel();
   { font-size: $font-size-p-large !important; }
}
.right
{ float: right;
  @include panel();
}
}
</source>
</source>


In diese SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:
In dieser SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:


* Import-Befehl: <code>@import 'config';</code>
* Import-Befehl: <code>@import 'config';</code>
* Konstanten:  <code>&#36;font-family-sans</code>, <code>&#36;font-family-serif</code>, <code>&#36;background-color</code>
* Konstanten:  <code>&#36;font-family-sans</code>, <code>&#36;font-size-base</code> etc. (Es sind noch viele weitere konstante Werte in <code>body.scss</code> enthalten, für die in <code>_config.scss</code> Konstanten definiert werden sollten)
* Verschachtelte Anweisungen: {{zB}} <code>h1</code> innerhalb von  <code>#section_form</code>
* Verschachtelte Anweisungen: {{zB}} <code>h1</code> innerhalb von  <code>#section_form</code>
* Mixins, um eine Liste von Attributen nur einmal zu definieren und und mehreren Elemente wieder verwenden zu können.


Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr
Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr
notwendig einen Selektor wie <code>#section_form</code> mehrfach zu verwenden.
notwendig, einen Selektor wie <code>#section_form</code> mehrfach zu verwenden.


Sehen Sie sich den Unterschied an. In der Datei <code>main.css</code> vom vierten Teil des Tutoriums hatten Sie
Sehen Sie sich den Unterschied an. In der Datei <code>src/css/body.css</code> der Musterlösungen vom dritten  Teil des Tutoriums hatte ich
folgendes geschrieben:
Folgendes geschrieben:


<source lang="CSS">
<source lang="CSS">
#section_form
#section_form
{
{ text-align:  center;
  text-align:  center;
  width:        21em;
   margin-left:  auto;
   margin-left:  auto;
   margin-right: auto;
   margin-right: auto;
Zeile 228: Zeile 260:


#section_form > h1
#section_form > h1
{
{ margin-bottom: 0.5ex; }
  font-size:    200%;
  margin-bottom: 0.5ex;
}
</source>
</source>


Zeile 239: Zeile 268:
#section_form
#section_form
{ text-align:  center;
{ text-align:  center;
  width:        21em;
   margin-left:  auto;
   margin-left:  auto;
   margin-right: auto;
   margin-right: auto;


   h1
   h1
   { font-size:    200%;
   { margin-bottom: 0.5ex; }
    margin-bottom: 0.5ex;
  }
}
}
</source>
</source>
Zeile 252: Zeile 278:
Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.
Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.


Ein weiteres Element, das nur SCSS bietet sind die Mixins. Sie definieren zunächst ein Mixin,
===Weitere SCSS-Konstrukte===
das eine Folge von CSS-Attributen zusammenfasst. (Auch hier könnten wieder Verschachtelungen und
andere SCSS-Erweiterungen verwendet werden!)


<source lang="CSS">
SCSS ist sehr mächtig. Es gibt neben der Import-Anweisung eine Use-Anweisung (<code>@use</code>)<ref>https://sass-lang.com/documentation/at-rules/use</ref>, die SCSS-Konstrukten im Gegensatz zur Import-Anweisung einen Namespace zuweist. Damit ist es möglich, mehrere SCSS-Module zu verwenden, auch wenn
@mixin panel()
dieses gleichbenannte Elemente enthalten, ohne dass es zu Namenskollisionen kommt.
{ padding: 0;
  width:  50%;
}
</source>
 
Und nun können Sie dieses Mixin in diversen andere Elemente einbinden:


<source lang="CSS">
Darüber hinaus gibt es Mixins<ref>https://sass-lang.com/documentation/at-rules/mixin</ref> und Funktionen<ref>https://sass-lang.com/documentation/at-rules/function</ref>. Mit Mixins kann man ganze Styleblöcke definieren, um sie mehrfach zu verwenden. Mixins werden mit <code>@include</code> eingebunden. Dabei kann man Argumente an die Mixins übergeben, mit denen die entsprechenden Konstanten innerhalb des Mixins initialisiert werden. Funktionen funktionieren wie Funktionen in anderen Programmiersprachen auch. Es stehen einem If-Anweisungen und Schleifen-Befehle zur Verfügung.
.left
{ float: left;
  @include panel();


.right
SCSS ist im Prinzip eine vollwertige Programmiersprache, um CSS-Dateien modular zu erstellen.
{ float: right;
  @include panel();
}
</source>


In normalen CSS-Code, müssten Sie denselben Code Non-DRY formulieren:
==Fortsetzung des Tutoriums==


<source lang="CSS">
Sie sollten nun [[HTML5-Tutorium: JavaScript: Hello World Vue 01|Teil 1 des Vue-Tutoriums]] bearbeiten.
.left
In diesem Teil des Tutoriums wird die oben erstelle Variante in das Vue-Framework transferiert.
{ float:  left;
  padding: 0;
  width:   50%;
}


.right
{ float:  right;
  padding: 0;
  width:  50%;
}
</source>
Wenn Sie hier das Layout der Panels ändern wollten (andere Breite, andere Ränder etc.), müssen
Sie den CSS-Code von jedem Panel einzeln ändern. In der SCSS-Datei erfolgt die Änderung dagegen DRY: Sie ändern einfach den Mixin-Code ab. 
==Wiederverwendbarkeit==
<!--
Hinsichtlich der Wiederverwendbarkeit der Module ist die [[HTML5-Tutorium: JavaScript: Hello World 05|Version 4]]
noch relativ schlecht.
Allerdings gibt es noch ein paar Unsauberkeiten, die beseitigt werden sollten:
# In den Initialisierungsdateien  „<code>main3.js</code>“ und  „<code>main3b.js</code>“ sind immer noch konstante Werte enthalten.
# Die Anzahl der Parameter der Konstruktorfunktion ist zu groß.
# In den Initialisierungsdateien ist immer noch zu viel Anwendungscode enthalten.
# Die potentielle Zahl der globalen Größen ist noch zu hoch.
Diese Probleme werden folgendermaßen gelöst:
# Die Konstanten werden in eine [[JSON]]-Datei ausgelagert, die im ersten Schritt von der jeweiligen Initialisierungsdatei eingelesen wird.
# Der Konstruktorfunktion wird das gesamte JSON-Objekt mit allen Initialisierungswerten in einem einzigen Parameter übergeben.
# Es wird eine anwendungsspezifische Initialisierungsdatei „<code>hello.js</code>“ erstellt. Die Initialisierungsfunktion in der Datei „<code>main4.js</code>“ hat nur noch die Aufgabe, die JSON-Datei zu lesen und die darin enthalten Informationen anschließend an die Methode  „<code>hello.init</code>“ weiterzuleiten.
# Es wird '''ein''' globales Objekt namens  „<code>hello</code>“ erstellt, das die gesamte Web-Anwendung enthält.
Erstellen Sie in Ihrem WebStorm-Projekt Kopien Ihrer Anwendungsdateien:
* <code>index3b.html</code> → <code>index4.html</code>
* <code>js/main3b.js</code> → <code>js/main4.js</code>
* <code>js/app3/greet.js</code> → <code>js/app4/greet.js</code>
Im Folgenden wird die HTML-Datei „<code>index4.html</code>“
als HTML-[[Template]] verwendet, {{dh}} als Strukturrahmen. '''Sämtliche''' Texte,
die in diesem Dokument enthalten sind, werden dynamisch mittels JavaScript eingefügt.
In der Datei „<code>index4.html</code>“ müssen Sie also nicht nur dafür sorgen, dass
die neuen JavaScript-Dateien anstelle der alten geladen werden und dass der Titel angepasst wird.
Sie müssen auch sämtliche Text-Elemente mit eindeutigen ID-Attributen versehen.
Die HTML-Datei der Musterlösung sieht folgendermaßen aus. Sie können auch Ihre
eigene Datei verwenden, müssen dann aber die JSON-Datei, die anschließend erstellt wird,
entsprechend anpassen.
<source lang="javascript">
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset = "UTF-8">
  <meta name    = "viewport"
        content = "width=device-width, initial-scale=1.0, user-scalable=yes"
  >
  <title>WK_HelloWorld04 (4)</title>
  <link rel = "stylesheet" type = "text/css" href = "css/main.css"/>
</head>
<body>
  <div class="left">
    <section id="section1_form">
      <h1 id="heading1_form"></h1>
      <form>
        <div>
          <label id="label1_name" for="input1_name"></label>
          <input id="input1_name" type="text" autofocus="autofocus"/>
        </div>
        <div>
          <button id="button1_reset"  type="reset"></button>
          <button id="button1_submit" type="button"></button>
        </div>
      </form>
    </section>
    <section id="section1_hello" class="hidden">
      <h1 id="heading1_hello"></h1>
      <p id="paragraph1_hello"></p>
    </section>
  </div>
  <div class="right">
    <section id="section2_form">
      <h1 id="heading2_form"></h1>
      <form>
        <div>
          <label id="label2_name" for="input2_name"></label>
          <input id="input2_name" type="text" autofocus="autofocus"/>
        </div>
        <div>
          <button id="button2_reset"  type="reset"></button>
          <button id="button2_submit" type="button"></button>
        </div>
      </form>
    </section>
    <section id="section2_hello" class="hidden">
      <h1 id="heading2_hello"></h1>
      <p id="paragraph2_hello"></p>
    </section>
  </div>
  <script type = "text/javascript" src = "js/lib/wk/ajax.js"></script>
  <script type = "text/javascript" src = "js/app4/greet.js"></script>
  <script type = "text/javascript" src = "js/app4/hello.js"></script>
  <script type = "text/javascript" src = "js/main4.js"></script>
</body>
</html>
</source>
-->
{{TBD}}
==Quellen==
==Quellen==
<references/>
<references/>
<ol>
<ol>
<li value="4"> {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}</li>
<li value="5"> {{Quelle|Kowarschick, W.: Web-Programmierung}}</li>
</ol>
</ol>
<noinclude>[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]</noinclude>
<noinclude>[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]</noinclude>

Aktuelle Version vom 18. April 2024, 09:27 Uhr

Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:

Korrektheit: 3
(zu größeren Teilen überprüft)
Umfang: 4
(unwichtige Fakten fehlen)
Quellenangaben: 3
(wichtige Quellen vorhanden)
Quellenarten: 5
(ausgezeichnet)
Konformität: 3
(gut)

Vorlesung WebProg

Inhalt | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5 | Teil 6 | Vue 1 | Vue 2 | Vue 3 | Vue 4 | Vue 5 | Vue 6

Musterlösung
v01: index.html (HTML validate)
v02: index.html (HTML validate; Modularisierung analog zu Hello World 04 v02)
v03: index.html (HTML validate; Konfiguration mittels JSON analog zu Hello World 04 v03)
Git-Repository

Anwendungsfälle (Use Cases)

Gegenüber dem dritten, vierten und fünften Teil des Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.

In diesem Teil des Tutoriums geht es darum, CSS durch SCSS zu ersetzen, um den CSS-Code „DRY zu machen“.

Erstellen eines neuen Projekts

Erstellen Sie ein neues Projekt hello_world_06 als Fork von hello_world_05.

SCSS

Anstelle von CSS-Dateien verwenden Sie künftig SCSS-Dateien. Das ist zunächst einmal nicht weiter schwer, das jede CSS-Datei automatisch auch eine SCSS-Datei ist. Bei der Verwendung von CSS können Sie allerdings das Prinzip „Don't repeat yourself“ (DRY) nicht beachten. Sie müssen für verschiedene Elemente ständig Informationen wiederholen (gewünschter Font, Hintergrundfarbe, Größenangaben etc.). Deshalb gibt es mehrere Projekte wie z. B. LESS, Sass/SCSS, Stylus, die den CSS-Standard erweitern, um dieses Problem zu vermeiden. Sass verwendet allerdings eine ganz andere Syntax als CSS. Allerdings unterstützt das Sass-Projekt auch die Sprache SCSS, die CSS einfach um weitere syntaktische Elemente ergänzt. Zum Beispiel kann man in SCSS Konstanten definieren:

$font-family-serif: "Times New Roman", Times, serif;

Und nun kann man in eine SCSS-Datei anstelle von "Times New Roman", Times, serif stets $font-family-serif schreiben, um den Font von bestimmten Elementen zu definieren.

p
{ font-family: $font-family-serif; }

label
{ font-family: $font-family-serif; }

Wenn man nun diesen Font ändern will, muss das nicht mehr bei allen Elementen einzeln passieren. Es reicht, die Konstantendefinition abzuändern. Der SCSS-Code ist nun DRY.

Weiterentwicklung von CSS

CSS entwickelt sich stetig weiter. Seit einiger Zeit werden auch hier Variablen unterstützt:

:root 
{ --font-family-serif: "Times New Roman", Times, serif; }

p
{ font-family: var(--font-family-serif); }

label
{ font-family: var(--font-family-serif); }

Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: math, CSS: calc). Das heißt, die Bedeutung von SCSS, Less etc. schwindet. Aber zurzeit bieten sie immer noch genügend mächtige Erweiterungen gegenüber CSS, wie z. B. die Möglichkeit, CSS-Elemente zu verschachteln, sodass sich der Einsatz von SCSS noch lohnt.

Transformation von SCSS in CSS

Leider unterstützt kein Browser SCSS direkt (im Gegensatz zu CSS). Aber für was gibt es Transpiler, die eine SCSS-Datei automatisch in eine CSS-Datei übersetzen können. Vite unterstützt CSS-Transpiler von Haus aus. Man muss den gewünschten Transpiler lediglich installieren:

npm i -D sass

Benennen Sie die Datei src/css/body.css in src/css/body.scss um. Ersetzen Sie außerdem in der Datei src/js/main.js den Import-Befehl

import '/css/body.css';

durch

import '/css/body.scss';

Wenn Sie Ihren Code nun mittels npm run dev laufen lassen oder mittels npm run build übersetzen, sollte die Anwendung noch funktionieren, da der SASS-Loader die neue SCCS-Datei in geeigneten CSS-Code übersetzt.

Schwieriger ist der direkte Import von head.scss in der Datei index.html, da diese SCSS-Datei von Vite nicht in CSS transformiert wird. Ein Workaround für dieses Problem wird später vorgestellt.

Vite-Konfiguration

Fügen Sie "config" als Abkürzung für "./src/css/_config.scss" in die Datei vite.config.js ein.

...
  resolve:
  { alias:
    { ...
      'config': fileURLToPath(new URL('./src/css/_config.scss', import.meta.url)),
      ...
    }
  }
...

SCSS-Konfiguration

In der Datei _config.scss werden alle von den anderen SCSS-Dateien benötigten Konstanten definiert. Das heißt, das DRY-Prinzip „Konstanten gehören nicht in den Code, sondern in Konfigurationsdateien“ wird ab sofort beachtet. Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will, reicht es, die entsprechenden Konstanten anzupassen und schon erzeugt Vite automatisch aktualisiere CSS-Dateien.

Der Underscore _ am Beginn des Dateinamens deutet an, dass diese SCSS-Datei nur von anderen SCSS-Dateien aber nicht von HTML- oder JavaScript-Dateien importiert werden. Durch SCSS-Import-Befehle ist es möglich, auch SCSS-Dateien zu modularisieren.

src/css/_config.scss

@use 'sass:math';

$background-color:  #C5EFFC;

$font-family-sans:  Verdana, Helvetica, sans-serif;
$font-family-serif: "Times New Roman", Times, serif;

$font-size-base:    3vw;
$font-size-factor:  1.25;  /* cmp. https://type-scale.com/ */
 
$font-size-h5:      math.pow($font-size-factor,1)*$font-size-base;
$font-size-h4:      math.pow($font-size-factor,2)*$font-size-base;
$font-size-h3:      math.pow($font-size-factor,3)*$font-size-base;
$font-size-h2:      math.pow($font-size-factor,4)*$font-size-base;
$font-size-h1:      math.pow($font-size-factor,5)*$font-size-base;

$font-size-p:       math.pow($font-size-factor,0)*$font-size-base;
$font-size-p-large: math.pow($font-size-factor,2)*$font-size-base;

$font-size-small:   math.pow($font-size-factor,-1)*$font-size-base;

In dieser SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:

  • Mathematische Berechnungen: @use 'sass:math';
  • Definition von Konstanten (die teilweise per Berechnung ermittelt werden)
  • Fonts sollten aus designerischen Gründen besser lokal gespeichert und per CSS eingebunden werden.

Konstanten starten in SCSS mit einem Dollarzeichen. Sobald eine Konstante definiert wurde, kann sie in allen weiteren SCSS-Konstrukten verwendet werden. In SCSS stehen einen Operatoren zur Verfügung wie +, -, * und /, um Maße zu berechnen. Es gibt weitere Operatoren zum Vergleichen von Zahlen und Maßen sowie zur Berechnung von Strings und booleschen Werten: https://sass-lang.com/documentation/operators.[1]

Die Datei _config.scss kann nun mit Hilfe des SCSS-Befehls @import 'config'; (ohne Underscore und ohne Endung, wegen der zuvor eingeführten Vite-Aliase) in die anderen beiden SCSS-Dateien eingefügt werden. Das Sass-Package kennt diesen Befehl und führt ihn beim Erstellen der zugehörigen CSS-Dateien auch aus.

Der Import-Befehl hat erst dann einen Effekt, wenn in den anderen Dateien auf diese Konstanten zugegriffen wird. Aber er schadet auch nicht, wenn auf keine der dort definierten Konstanten zugegriffen wird. Der Import-Befehl selbst taucht ebenso wenig in den generierten CSS-Dateien auf, wie die Konstantendefinitionen. Der Transpiler ersetzt Konstanten in CSS-Definitionen durch ihren jeweiligen Wert.

Sie können nun beispielsweise in der Datei head.scss die Konstante $background-color verwenden. In der daraus erzeugten CSS-Datei steht weiterhin der Farbwert #C5EFFC;

src/css/head.scss

@import 'config';

body
{ background-color: $background-color; }

.hidden
{ display: none; }

Die Datei body.scss ist deutlich umfangreicher. Daher wird der zugehörige CSS-Code ja auch erst dynamisch gemeinsam mit der Datei web/js/main.js geladen.

src/css/body.scss

@import 'config';

html
{ height:  100%;
  width:   100%;
  display: table;
}

body
{ display:          table-cell;
  text-align:       center;
  vertical-align:   middle;
  background-color: $background-color;
  font-size:        $font-size-base !important;
  font-family:      $font-family-sans;
}

h1
{ padding:   0;
  margin:    0;
  font-size: $font-size-h1;
}

p, label
{ font-family: $font-family-serif;
  font-size:   $font-size-p !important;
}

label, input, button
{ width:      10em;
  font-size:  100%;
  display:    inline-block;
  box-sizing: border-box;
  margin:     0.5ex;
}

label
{ text-align: right;
}

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;

  h1
  { margin-bottom: 0.5ex; }
}

#section_hello
{ p
  { font-size: $font-size-p-large !important; }
}

In dieser SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:

  • Import-Befehl: @import 'config';
  • Konstanten: $font-family-sans, $font-size-base etc. (Es sind noch viele weitere konstante Werte in body.scss enthalten, für die in _config.scss Konstanten definiert werden sollten)
  • Verschachtelte Anweisungen: z. B. h1 innerhalb von #section_form

Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr notwendig, einen Selektor wie #section_form mehrfach zu verwenden.

Sehen Sie sich den Unterschied an. In der Datei src/css/body.css der Musterlösungen vom dritten Teil des Tutoriums hatte ich Folgendes geschrieben:

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;
}

#section_form > h1
{ margin-bottom: 0.5ex; }

Die SCSS-Variante ist deutlich strukturierter und prägnanter.

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;

  h1
  { margin-bottom: 0.5ex; }
}

Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.

Weitere SCSS-Konstrukte

SCSS ist sehr mächtig. Es gibt neben der Import-Anweisung eine Use-Anweisung (@use)[2], die SCSS-Konstrukten im Gegensatz zur Import-Anweisung einen Namespace zuweist. Damit ist es möglich, mehrere SCSS-Module zu verwenden, auch wenn dieses gleichbenannte Elemente enthalten, ohne dass es zu Namenskollisionen kommt.

Darüber hinaus gibt es Mixins[3] und Funktionen[4]. Mit Mixins kann man ganze Styleblöcke definieren, um sie mehrfach zu verwenden. Mixins werden mit @include eingebunden. Dabei kann man Argumente an die Mixins übergeben, mit denen die entsprechenden Konstanten innerhalb des Mixins initialisiert werden. Funktionen funktionieren wie Funktionen in anderen Programmiersprachen auch. Es stehen einem If-Anweisungen und Schleifen-Befehle zur Verfügung.

SCSS ist im Prinzip eine vollwertige Programmiersprache, um CSS-Dateien modular zu erstellen.

Fortsetzung des Tutoriums

Sie sollten nun Teil 1 des Vue-Tutoriums bearbeiten. In diesem Teil des Tutoriums wird die oben erstelle Variante in das Vue-Framework transferiert.

Quellen

  1. Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)