Hallo Joachim,
Der Nutzer soll sich eine Aufgabe durch Klick aussuchen
Gute Idee. Aber warum dafür auf einen Extrabutton klicken? Warum dafür eine aufwändige UI-Steuerung?
dann ist entweder der Focus auf dem Eingabefeld oder er hat den Link zur Lösung.
Das gelingt, indem die Nutzerin per Klick ein Eingabefeld auswählt (womit Du übrigend etwas sparsam bist - ist es Absicht, dass einige Aufgaben keine Eingabefelder haben?)
Spricht denn etwas dagegen, alle Eingabefelder ständig offen zu haben? Und daneben zwei Buttons: "Überprüfen" und "Lösung" - jederzeit verfügbar. Es ist überhaupt nicht sinnvoll, den Lösung-Button erstmal vorzuenthalten. Wer sich selbst täuschen und einfach die Lösung nachgucken will, der trägt einfach Müll ein und ruft dann die Lösung ab.
Es ist auch nicht nötig, Aufgaben nebeneinander zu setzen. Das ist Papierform-Denke, wie Felix schon sagte.
Die Idee, immer nur eine Aufgabe anzubieten und eine Zufallsauswahl zu erstellen, ist sicherlich auch denkbar, aber dann sieht deine Seite ganz anders aus.
Wenn Du eine Aufgabenliste hast und sie per Grid in einem Raster anordnen willst (2xN bei breitem Fenster, 1xN bei schmalem Fenster), dann ist relevant was Jonathan sagte. Eine Flexbox und auch ein Grid bestehen aus einem Container - das Element mit display:flex oder display:grid - und den Flex-Items oder Grid-Items. Die Items sind die direkten Kindelemente des Containers (abgesehen von display:contents, was ich hier nicht diskutieren will).
Aber, wie gesagt, die Mühe mit einer zweispalten Aufgabendarstellung würde ich mir nicht machen. Das bringt deinen Schülern keinen Mehrwert, und es ignoriert eine wesentliche Eigenschaft von Webseiten: Sie sind beliebig weit scrollbar. Bei Textinhalten ist es besser, nur in einer Richtung scrollen zu müssen.
Eine interessante Frage ist, ob Du den Anleitungstext immer sichtbar halten möchtest, auch wenn gescrollt wird. Das kann man mit position:sticky oder einem body-Layout lösen, das dafür sorgt, dass nur ein Teil des Body scrollt.
Dass nur ein Teil des Body scrollt, erreicht man prinzipiell so:
<body>
<header>
</header>
<main>
</main>
</body>
body {
margin: 0;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr;
}
header {
grid-row: 1;
}
main {
grid-row: 2;
overflow-y: scroll;
}
Mit Flexbox oder einer Position:absolute-Orgie lässt sich das auch realisieren, aber Grid ist für solche Layout-Aufgaben eigentlich Mittel der Wahl. Ich habe jetzt nur header und main als Seitenregionen gezeigt. Sicherlich gibt's noch eine Navigation. Das dafür zuständige <nav>-Element kann entweder ein Kind des <header> sein und fällt dann in dessen Layout-Zuständigkeit, oder es ist ein eigenes Kind des <body> und muss dann über dessen Grid-Layout verwaltet werden. Üblicher ist es, daraus ein Kind des <body> zu machen. Per Grid-Layout kannst Du header und nav entweder untereinander oder nebeneinander setzen. Wie möchtest Du es haben?
Innerhalb von main kommen dann die Aufgaben. Hier sollte jede Aufgabe ein eigenes Container-Element haben. Semantisch passend ist das <article>-Element. ABER ich würde Dir eher ein Formular empfehlen. Damit könntest Du, wenn Du möchtest, die Auswertung auch mit einer Scriptsprache auf dem Server machen.
<form class="aufgabe" name="aufgabe_1">
<h2>Aufgabe 1</h2>
<p class="text">Aufgabentext</p>
<label class="versuch">Ihr Versuch: <input type="text"></label>
<button name="verify">Prüfen</button>
<a href="..." target="_blank">Lösung</a>
</form>
Diese 5 Elemente musst Du nun nach Geschmack anordnen. Hierfür bietet sich wieder Grid an, damit kannst Du über eine @media-Abfrage auch automatisch dafür sorgen, dass bei einem breiteren Fenster die Darstellung wechselt. Erstmal die schmale Darstellung:
.aufgabe {
display: grid;
grid: "h2 h2 " auto
"text text" auto
"vers lsng" auto
/ 1fr auto;
}
.aufgabe h2 {
grid-area: h2;
}
.aufgabe .text {
grid-area: text;
}
.aufgabe .versuch {
grid-area: vers;
text-align: right;
}
.aufgabe button {
grid-area: prüf;
justify-self: end;
}
.aufgabe a {
grid-area: lsng;
}
.aufgabe input {
width: 6em;
}
.aufgabe :is(button, a) {
width: 4.5em;
/* plus etliches Zeugs zur visuallen Angleichung a / button */
}
Das ist jetzt nur die rudimentäre Grid-Verteilung. Die Verwendung der grid-Eigenschaft hat die schöne Eigenschaft, dass man sich sein Layout sozusagen per ASCII-Kunst „malen“ kann. Für jede Zeile, die man möchte, schreibt man eine Namensliste in Anführungszeichen und die Höhe (hier immer auto). Die Namensliste besteht aus sovielen Namen, wie man Spalten haben möchte (hier 2). Ich habe hier also ein Raster von 3×2=6 Zellen definiert. Nun habe ich Layoutelemente, die in diesem Raster "aufgehängt" werden sollen. Dafür denke ich mir Namen aus, z.B. "h2" für die Überschrift - aber ich hätte für die Überschrift auch den Namen "xy" oder "Fridolin" verwenden können. Die Überschrift soll Spalte 1-2 der ersten Zeile belegen, darum schreibe ich ihren Namen in diese 2 Zellen.
Der Text soll die ganze zweite Zeile, der Eingabebereich die ganze dritte Zeile belegen. Mit text-align:right sorge ich dafür, dass Label und Eingabefeld am rechten Rand stehen.
In die vierte Zeile kommen der Prüfen-Button und der Lösung-Link. Ja, Link, denn du öffnest ja eine neue Seite und das gelingt mit <a target="_blank"> ohne weiteres Script.
Hinter den Zeilendefinitionen folgt ein Schrägstrich und dann die Angabe der Spaltenbreiten. Die erste Spalte bekommt 1fr - mehr dazu im Wiki. Hier bedeutet es: Die erste Spalte nimmt, was die zweite nicht braucht. Die zweite Spalte ist "auto" breit, was den Lösungs-Link zum bestimmenden Element für ihre Breite macht.
Für die Grid-Items wird über die grid-area Eigenschaft festgelegt, in welchem benannten Bereich sie dargestellt werden sollen. Der Prüfen-Button hat eine Besonderheit: seine Spalte nimmt typischerweise mehr Raum ein als der Button braucht. Damit er am rechten Rand der Spalte steht, wird das Grid-Item per justify-self: end; an die rechte Seite platziert. Warum nicht mit text-align, wie beim Eingabefeld? Beim Eingabefeld ging es um den Inhalt des Grid-Items. Würde ich dort justify-self:end verwenden, dann wäre der Inhalt innerhalb des Labels links ausgerichtet. Das fällt bei sehr schmalen Viewports auf.
Auf breiten Fenstern kann man Eingabe und Buttons nebeneinander setzen. Dafür kann man das Grid-Layout über eine @media-Abfrage ersetzen:
@media (width > 20em) {
.aufgabe {
grid: "h2 h2 h2 " auto
"text text text" auto
"vers prüf lsng" auto
/ 1fr auto auto;
}
}
Ich habe hier ein Fiddle, dass das zeigt: https://jsfiddle.net/prb8c67d/. Wenn Du mit der Breite des Ausgabebereichs spielst, siehst Du die Effekte.
Rolf
sumpsi - posui - obstruxi