Als Helferklassen sind .form-row und .form-label-offset definiert.
.form-row ist für die gestrichelte Linie und Einzüge verantwortlich.
.form-label-offset kann benutzt werden, um eine Eingabefeld ohne Label korrekt einzurücken. Siehe im Beispiel die zweite Aktiv-Checkbox.
Ansonsten ist im Moment alles über den Bootstrap-Standard lösbar.
Für die Darstellung der Werte wird ein <span class="form-control-plaintext"> verwendet.
Auswahlfelder, die über Tom Select initialisiert werden, sind im Standard durchsuchbar.
Hier zwei Beispiele für JavaScript-Optionen, Sortierung und externe Daten.
new TomSelect('#search_select',{
valueField: 'id',
searchField: ['lastName', 'firstName'],
sortField: {
field: 'lastName',
direction: 'asc'
},
render: {
option: function (item, escape) {
return `<div>${escape(item.lastName)}, ${escape(item.firstName)}</div>`;
},
item: function (item, escape) {
return `<div>${escape(item.firstName)} ${escape(item.lastName)}</div>`;
}
},
options: [
{ "id": 1, "lastName": "Schneider", "firstName": "Wilhelm" },
{ "id": 2, "lastName": "Weber", "firstName": "Elisabeth" },
{ "id": 3, "lastName": "Müller", "firstName": "Karl" },
{ "id": 4, "lastName": "Fischer", "firstName": "Maria" },
{ "id": 5, "lastName": "Meyer", "firstName": "Otto" },
{ "id": 6, "lastName": "Wagner", "firstName": "Anna" },
{ "id": 7, "lastName": "Becker", "firstName": "Friedrich" },
{ "id": 8, "lastName": "Schmidt", "firstName": "Martha" },
{ "id": 9, "lastName": "Neumann", "firstName": "Heinrich" },
{ "id": 10, "lastName": "Hoffmann", "firstName": "Helene" },
{ "id": 11, "lastName": "Schmitt", "firstName": "Gustav" },
{ "id": 12, "lastName": "Koch", "firstName": "Emma" },
{ "id": 13, "lastName": "Bauer", "firstName": "Paul" },
{ "id": 14, "lastName": "Schulz", "firstName": "Sophie" },
{ "id": 15, "lastName": "Maier", "firstName": "Georg" },
{ "id": 16, "lastName": "Klein", "firstName": "Gertrud" },
{ "id": 17, "lastName": "Wolf", "firstName": "Konrad" },
{ "id": 18, "lastName": "Braun", "firstName": "Auguste" },
{ "id": 19, "lastName": "Schwarz", "firstName": "Werner" },
{ "id": 20, "lastName": "Zimmermann", "firstName": "Frieda" },
{ "id": 21, "lastName": "Weiß", "firstName": "Walter" },
{ "id": 22, "lastName": "Hartmann", "firstName": "Martha" },
{ "id": 23, "lastName": "Lange", "firstName": "Hermann" },
{ "id": 24, "lastName": "Wild", "firstName": "Adele" },
{ "id": 25, "lastName": "Meier", "firstName": "Richard" },
{ "id": 26, "lastName": "Wagner", "firstName": "Auguste" },
{ "id": 27, "lastName": "Schröder", "firstName": "Otto" },
{ "id": 28, "lastName": "Meyer", "firstName": "Emma" },
{ "id": 29, "lastName": "Huber", "firstName": "Paul" },
{ "id": 30, "lastName": "Krause", "firstName": "Sophie" }
]
});
new TomSelect('#remote_data_select',{
valueField: 'url',
labelField: 'name',
searchField: 'name',
load: function(query, callback) {
var url = 'https://api.github.com/search/repositories?q=' + encodeURIComponent(query);
fetch(url)
.then(response => response.json())
.then(json => {
callback(json.items);
}).catch(()=>{
callback();
});
}
});
@use "sass:math";
.form-row {
padding: 0 0 ($spacer * .5) 0;
position: relative;
&::after {
border-bottom: 1px dotted rgba($primary, .5);
bottom: 0;
content: '';
position: absolute;
}
@each $key, $gutter in $gutters {
&.g-#{$key}::after,
&.gx-#{$key}::after {
left: calc($gutter / 2);
right: calc($gutter / 2);
}
}
}
.form-label-offset {
&::before {
content: '\00a0';
display: block;
@include font-size($form-label-font-size);
margin-bottom: $form-label-margin-bottom;
}
}
.form-control-display {
@extend .form-control-plaintext;
font-size: $input-font-size;
padding-left: 0;
padding-right: 0;
// margin: -(math.div($form-label-margin-bottom, 5) * 4) 0 0 0;
// Prevent empty elements from collapsing.
&::before {
content: '\200b';
user-select: none;
}
}
textarea[class*="form-control"] {
padding-bottom: $input-btn-padding-x * 0.75;
padding-top: $input-btn-padding-x * 0.75;
&.form-control {
min-height: 90px;
}
&.form-control-sm {
min-height: 90px;
padding-bottom: $input-padding-x-sm;
padding-top: $input-padding-x-sm;
}
&.form-control-lg {
min-height: 120px;
padding-bottom: $input-padding-x-lg;
padding-top: $input-padding-x-lg;
}
}
///// File zone
.form-file-zone {
p {
display: none;
&:last-child {
margin-bottom: 0;
}
}
&.form-file-zone-dd {
background-color: $gray-100;
display: block;
padding: $spacer * 3;
text-align: center;
&.form-file-zone-dragover {
background-color: $gray-400;
}
p {
display: block;
}
label {
cursor: pointer;
text-decoration: underline;
&:hover {
color: var(--bs-link-hover-color);
}
}
input[type="file"] {
@include visually-hidden;
}
}
}
///// Tom Select
// To keep everything on a single line and have the options not run into and
// overlay the select indicator, we're removing it from .form-select and rebuild
// everything inside .ts-control.
// Kinda wonky but we couldn't just cut .ts-control in width as it is responsible
// for triggering the dropdown and that would've left a blank spot from .ts-wrapper
// that wouldn't trigger the dropdown (where the original indicator actually would be).
.ts-wrapper.form-select {
background-image: none;
.ts-control {
flex-wrap: nowrap;
gap: 9px;
position: relative;
&::before {
background-image: var(--#{$prefix}form-select-bg-img), var(--#{$prefix}form-select-bg-icon, none);
background-repeat: no-repeat;
background-position: $form-select-bg-position;
background-size: $form-select-bg-size;
background-color: $gray-100;
content: '';
height: 100%;
position: absolute;
right: 0;
top: 0;
width: $form-select-indicator-padding;
}
&::after {
background: linear-gradient(90deg, rgba($gray-100, 0) 0%, rgba($gray-100, 1) 100%);
content: '';
height: 100%;
position: absolute;
right: $form-select-indicator-padding;
top: 0;
width: 15px;
}
.item {
text-wrap: nowrap;
}
}
&:not(.multi-select) .ts-control .item {
color: $primary;
text-wrap: nowrap;
}
}
.ts-wrapper.form-select.focus .ts-control {
flex-wrap: wrap;
}
.ts-wrapper.multi .ts-control > div {
background-color: $primary;
box-shadow: 0 0 0 3px $primary;
color: #fff;
white-space: nowrap;
line-height: 1;
margin: 0;
}
.ts-dropdown,
.ts-dropdown.form-control,
.ts-dropdown.form-select {
border-radius: 0;
}
.ts-wrapper.dropdown-top .ts-dropdown {
bottom: 100%;
top: auto;
}
.ts-dropdown .option,
.ts-dropdown .optgroup-header,
.ts-dropdown .no-results,
.ts-dropdown .create {
line-height: 1.1;
padding-bottom: 8px;
padding-top: 8px;
&[aria-disabled] {
cursor: default;
}
}
.ts-dropdown .option.selected {
font-weight: 700;
}
// Additional .form-select to beat specificity from library.
.input-group-sm > .ts-wrapper.has-items,
.ts-wrapper.form-select.form-select-sm.has-items,
.ts-wrapper.form-select.form-control-sm.has-items {
.ts-control {
padding-bottom: $input-padding-y-sm !important;
padding-left: $input-padding-x-sm; // Offset from box-shadow for items. See above.
padding-top: $input-padding-y-sm !important;
}
.ts-dropdown .option, .ts-dropdown .optgroup-header,
.ts-dropdown .no-results,
.ts-dropdown .create {
padding-left: $input-padding-x-sm;
padding-right: $input-padding-x-sm;
}
}
<form class="d-flex flex-column gap-3">
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="salutation" class="form-label">Anrede</label>
<select id="salutation" class="form-select w-25">
<option selected>Bitte wählen …</option>
<option>…</option>
</select>
</div>
<div class="col-md-6">
<label for="academic_title" class="form-label">Akademischer Titel</label>
<input type="text" class="form-control " id="academic_title">
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="first_name" class="form-label">Vorname</label>
<input type="text" class="form-control" id="first_name" value="Hubert">
</div>
<div class="col-md-6">
<label for="last_name" class="form-label">Nachname</label>
<input type="text" class="form-control" id="last_name" value="Hubschrauber" disabled>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="position" class="form-label">Position</label>
<input type="text" class="form-control" id="position">
</div>
<div class="col-md-6">
<label for="account" class="form-label">Account</label>
<input type="text" class="form-control" id="account">
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="email_1" class="form-label">E-Mail-Adresse #1</label>
<input type="email" class="form-control" id="email_1">
</div>
<div class="col-md-6">
<label for="email_2" class="form-label">E-Mail-Adresse #1</label>
<input type="email" class="form-control" id="email_2">
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-4">
<label for="multi_select" class="form-label">Erweiterte Mehrfachauswahl</label>
<select id="multi_select" class="form-select multi-select" multiple>
<option selected>Option 1</option>
<option>Option 2</option>
<option selected>Option 3</option>
<option>Option 4</option>
<option selected>Option 5</option>
<option selected>Option 6</option>
<option selected>Option 7</option>
<option>Option 8</option>
<option selected>Option 9</option>
<option selected>Option 10</option>
</select>
</div>
<div class="col-md-4">
<label for="search_select" class="form-label">Durchsuchbar</label>
<select id="search_select" class="form-select" autocomplete="off"></select>
</div>
<div class="col-md-4">
<label for="remote_data_select" class="form-label">Durchsuchbar, externe Daten</label>
<select id="remote_data_select" class="form-select" autocomplete="off"></select>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="role" class="form-label">Benutzer / Rolle</label>
<select id="role" class="form-select">
<option>Bitte wählen …</option>
<option value="manager" selected>Core Spot Manager</option>
<option>…</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label d-block" for="active-1">Aktiv</label>
<input class="form-check-input" type="checkbox" value="" id="active-1">
</div>
<div class="col-md-3 form-label-offset">
<input class="form-check-input" type="checkbox" value="" id="active-2">
<label class="form-check-label" for="active-2">Aktiv</label>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="annual_turnover" class="form-label">Jahresumsatz</label>
<div class="input-group">
<input id="annual_turnover" class="form-control" type="text" aria-describedby="annual_turnover_currency">
<span id="annual_turnover_currency" class="input-group-text">EUR</span>
</div>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="some-file" class="form-label">Datei</label>
<div class="form-file-zone form-file-zone-dd">
<input id="some-file" class="form-control" type="file">
<p>
<label for="some-file">Wählen Sie eine Datei aus</label> aus oder ziehen Sie sie in dieses Feld.
</p>
<p>Upload-Größe maximal 10 MB.</p>
</div>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-3">
<label class="form-label">Option #1</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="form-check-1">
<label class="form-check-label" for="form-check-1">
Option
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="form-check-2">
<label class="form-check-label" for="form-check-2">
Option
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="form-check-3">
<label class="form-check-label" for="form-check-3">
Option
</label>
</div>
</div>
<div class="col-md-3">
<label class="form-label">Option #2</label>
<div class="form-check">
<input class="form-check-input" type="radio" value="" name="radio-group" id="form-radio-1">
<label class="form-check-label" for="form-radio-1">
Option
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="" name="radio-group" id="form-radio-2">
<label class="form-check-label" for="form-radio-2">
Option
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="" name="radio-group" id="form-radio-3">
<label class="form-check-label" for="form-radio-3">
Option
</label>
</div>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-12">
<label for="description" class="form-label">Beschreibung</label>
<textarea class="form-control" id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</textarea>
</div>
</div>
<div class="row gx-5">
<div class="col-md-12 text-end">
<a href="#" class="btn btn-link">Abbrechen</a>
<button type="submit" class="btn btn-primary">Speichern</button>
</div>
</div>
</form>
<script>
</script>
<div class="d-flex flex-column gap-3">
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="salutation" class="form-label">Anrede</label>
<span class="form-control-display" id="salutation">Herr</span>
</div>
<div class="col-md-6">
<label for="academic_title" class="form-label">Akademischer Titel</label>
<span class="form-control-display" id="academic_title"></span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="first_name" class="form-label">Vorname</label>
<span class="form-control-display" id="first_name">Hubert</span>
</div>
<div class="col-md-6">
<label for="last_name" class="form-label">Nachname</label>
<span class="form-control-display" id="last_name">Hubschrauber</span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="position" class="form-label">Position</label>
<span class="form-control-display" id="position">Pilot</span>
</div>
<div class="col-md-6">
<label for="account" class="form-label">Account</label>
<a href="#" class="form-control-display" id="account">Musterfirma GmbH</a>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="email_1" class="form-label">E-Mail-Adresse #1</label>
<a href="#" class="form-control-display" id="email_1">h.hubschrauber@musterfirma.de</a>
</div>
<div class="col-md-6">
<label for="email_2" class="form-label">E-Mail-Adresse #2</label>
<span class="form-control-display" id="email_2"></span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="role" class="form-label">Benutzer / Rolle</label>
<span class="form-control-display" id="role">Core Spot Manager</span>
</div>
<div class="col-md-3">
<label class="form-label d-block" for="active-1">Aktiv</label>
<span class="form-control-display" id="active-1">Ja</span>
</div>
<div class="col-md-3 form-label-offset">
<span class="form-control-display" id="active-2">Aktiv</span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-6">
<label for="annual_turnover" class="form-label">Jahresumsatz</label>
<span class="form-control-display" id="annual_turnover">2.000.736 EUR</span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-3">
<label class="form-label" for="option-1">Option #1</label>
<span class="form-control-display" id="option-1">Option 2</span>
</div>
<div class="col-md-3">
<label class="form-label" for="option-2">Option #2</label>
<span class="form-control-display" id="option-2">Option 1, Option 3</span>
</div>
</div>
<div class="row form-row gx-5">
<div class="col-md-12">
<label for="description" class="form-label">Beschreibung</label>
<span class="form-control-display" id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</span>
</div>
</div>
<div class="row gx-5">
<div class="col-md-12 text-end">
<a href="#" class="btn btn-primary">Bearbeiten</a>
</div>
</div>
</div>
<form class="d-flex flex-column gap-3">
<div class="row gx-5">
<label for="salutation" class="col-md-2 col-form-label">Anrede</label>
<div class="col-md-3">
<select id="salutation" class="form-select">
<option selected>Bitte wählen …</option>
<option>…</option>
</select>
</div>
</div>
<div class="row gx-5">
<label for="academic_title" class="col-md-2 col-form-label">Akademischer Titel</label>
<div class="col-md-10">
<input type="text" class="form-control" id="academic_title">
</div>
</div>
<div class="row gx-5">
<label for="first_name" class="col-md-2 col-form-label">Vorname</label>
<div class="col-md-10">
<input type="text" class="form-control" id="first_name" value="Hubert">
</div>
</div>
<div class="row gx-5">
<label for="last_name" class="col-md-2 col-form-label">Nachname</label>
<div class="col-md-10">
<input type="text" class="form-control" id="last_name" value="Hubschrauber">
</div>
</div>
<div class="row gx-5">
<label for="description" class="col-md-2 col-form-label">Beschreibung</label>
<div class="col-md-10">
<textarea class="form-control" id="description">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</textarea>
</div>
</div>
<div class="row gx-5">
<div class="col-md-12 text-end">
<a href="#" class="btn btn-link">Abbrechen</a>
<button type="submit" class="btn btn-primary">Speichern</button>
</div>
</div>
</form>