diff --git a/lib/models/Courseware/BlockTypes/Gallery.json b/lib/models/Courseware/BlockTypes/Gallery.json
index a71ca363feb710cd15b37f2050a86506c1da648c..205816c0a7a5c1bdebc593f5c42a8162a01f4b9d 100644
--- a/lib/models/Courseware/BlockTypes/Gallery.json
+++ b/lib/models/Courseware/BlockTypes/Gallery.json
@@ -5,6 +5,9 @@
         "folder_id": {
             "type": "string"
         },
+        "layout": {
+            "type": "string"
+        },
         "autoplay": {
             "type": "string"
         },
@@ -17,9 +20,15 @@
         "height": {
             "type": "string"
         },
+        "cols": {
+            "type": "string"
+        },
         "show_filenames": {
             "type": "string"
         },
+        "show_description": {
+            "type": "string"
+        },
         "mouseover_filenames": {
             "type": "string"
         }
diff --git a/lib/models/Courseware/BlockTypes/Gallery.php b/lib/models/Courseware/BlockTypes/Gallery.php
index 7363a7c652aa38a73ee2a975eb1fb17d1f096ac5..5f9bb0b6d56d3c8c8d5acc5f503f09306cef3f8d 100644
--- a/lib/models/Courseware/BlockTypes/Gallery.php
+++ b/lib/models/Courseware/BlockTypes/Gallery.php
@@ -59,6 +59,7 @@ class Gallery extends BlockType
                     'name'          => $folderFile->name,
                     'mime-type'     => $folderFile->mime_type,
                     'filesize'      => (int) $folderFile->size,
+                    'description'   => $fileRef->description,
                     'mkdate'        => date('c', $folderFile->mkdate),
                 ];
                 $file['relationships'] = [
@@ -89,11 +90,14 @@ class Gallery extends BlockType
     {
         return [
             'folder_id' => '',
+            'layout' => 'carousel',
             'autoplay' => 'false',
             'autoplay_timer' => '2',
             'nav' => 'true',
-            'height' => '610',
+            'height' => '620',
+            'cols' => '25',
             'show_filenames' => 'true',
+            'show_description' => 'false',
             'mouseover_filenames' => 'false',
         ];
     }
diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss
index 1d3c1fe948b56ce981e00ef18f2a023ced52bae5..77e849103cbde1a743e527f39f5fa2f2db9293ca 100644
--- a/resources/assets/stylesheets/scss/courseware.scss
+++ b/resources/assets/stylesheets/scss/courseware.scss
@@ -3807,17 +3807,22 @@ g a l l e r y  b l o c k
     }
 }
 
-.cw-block-gallery-file-name {
-    color: $white;
+.cw-block-gallery-file-description {
+    width: -moz-available;
+    color: var(--white);
     font-size: 15px;
     padding: 8px 12px;
     position: absolute;
     bottom: 8px;
-    width: 100%;
     text-align: center;
-    span {
+    p {
+        display: -webkit-inline-box;
         background-color: fade-out($black, 0.6);
-        padding: 0.5em;
+        padding: 0 2em;
+        margin-bottom: 4px;
+        overflow: hidden;
+        -webkit-line-clamp: 3;
+        -webkit-box-orient: vertical;
     }
 
     &.show-on-hover {
@@ -3830,7 +3835,7 @@ g a l l e r y  b l o c k
 }
 
 .cw-block-gallery-number-text {
-    color: $white;
+    color: var(--white);
     font-size: 12px;
     padding: 8px 12px;
     position: absolute;
@@ -3855,6 +3860,41 @@ g a l l e r y  b l o c k
     to {opacity: 1}
 }
 
+
+.cw-block-gallery-grid {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: flex-start;
+    list-style: none;
+    padding: 0;
+    figure {
+        padding: 1px 4px;
+        margin: unset;
+        figcaption {
+            margin-bottom: 12px;
+
+            .cw-block-gallery-grid-file-name {
+                font-weight: 700;
+                margin-bottom: 4px;
+                overflow: hidden;
+                display: -webkit-box;
+                -webkit-line-clamp: 2;
+                -webkit-box-orient: vertical;
+            }
+            .cw-block-gallery-grid-file-description {
+                overflow: hidden;
+                display: -webkit-box;
+                -webkit-line-clamp: 5;
+                -webkit-box-orient: vertical;
+            }
+        }
+    }
+}
+.cw-container-wrapper-edit .cw-block-gallery-grid {
+    margin: 0;
+}
+
 /* * * * * * * * * * * * * * * * *
 g a l l e r y  b l o c k  e n d
 * * * * * * * * * * * * * * * * */
diff --git a/resources/vue/components/courseware/CoursewareGalleryBlock.vue b/resources/vue/components/courseware/CoursewareGalleryBlock.vue
index f6d41ab74e07da0af8f0dbe70b56fa4a34ffa0cc..ff730d09b2436c61445217ceda633fd9f90a5100 100644
--- a/resources/vue/components/courseware/CoursewareGalleryBlock.vue
+++ b/resources/vue/components/courseware/CoursewareGalleryBlock.vue
@@ -10,82 +10,152 @@
             @closeEdit="closeEdit"
         >
             <template #content>
-                <div v-if="files.length !== 0" class="cw-block-gallery-content" :style="{ 'max-height': currentHeight + 'px' }">
-                    <div
-                        v-for="(image, index) in files"
-                        :key="image.id"
-                        ref="images"
-                        class="cw-block-gallery-slides cw-block-gallery-fade"
-                    >
-                        <div class="cw-block-gallery-number-text">{{ index + 1 }} / {{ files.length }}</div>
-                        <img
-                            :src="image.meta['download-url']"
-                            :style="{ 'max-height': currentHeight + 'px' }"
-                            @load="
-                                if (files.length - 1 === index) {
-                                    startGallery();
-                                }
-                            "
-                        />
-                        <div v-if="currentShowFileNames === 'true' && image?.attributes?.name" class="cw-block-gallery-file-name"
-                            :class="{'show-on-hover': currentMouseoverFileNames === 'true'}">
-                            <span>{{ image.attributes.name }}</span>
+                <template v-if="files.length !== 0">
+                    <div v-if="currentLayout === 'carousel'" class="cw-block-gallery-content" :style="{ height: `${currentHeight}px` }">
+                        <div
+                            v-for="(image, index) in files"
+                            :key="image.id"
+                            ref="images"
+                            class="cw-block-gallery-slides cw-block-gallery-fade"
+                        >
+                            <div class="cw-block-gallery-number-text">{{ index + 1 }} / {{ files.length }}</div>
+                            <img
+                                :src="image.meta['download-url']"
+                                :style="{ height: `${currentHeight}px` }"
+                                @load="
+                                    if (files.length - 1 === index) {
+                                        startGallery();
+                                    }
+                                "
+                            />
+                            <div class="cw-block-gallery-file-description"
+                                :class="{'show-on-hover': currentMouseoverFileNames === 'true'}">
+                                <p v-if="currentShowFileNames === 'true'">{{ image?.attributes?.name }}</p>
+                                <p v-if="currentShowFileDescription === 'true'">{{ image?.attributes?.description }}</p>
+                            </div>
+                        </div>
+                        <div v-if="currentNav === 'true'">
+                            <a class="cw-block-gallery-prev" @click="plusSlides(-1)"></a>
+                            <a class="cw-block-gallery-next" @click="plusSlides(1)"></a>
                         </div>
                     </div>
-                    <div v-if="currentNav === 'true'">
-                        <a class="cw-block-gallery-prev" @click="plusSlides(-1)"></a>
-                        <a class="cw-block-gallery-next" @click="plusSlides(1)"></a>
+                    <div v-if="currentLayout === 'grid'" class="cw-block-gallery-content">
+                        <div class="cw-block-gallery-grid formatted-content">
+                            <figure
+                                v-for="image in files"
+                                :key="image.id"
+                                :style="{ 'max-width': gridWidth }"
+                            >
+                                <img :src="image.meta['download-url']" :title="image?.attributes?.name"/>
+                                <figcaption v-if="showDescription">
+                                    <p v-if="currentShowFileNames === 'true'" class="cw-block-gallery-grid-file-name">
+                                        {{ image?.attributes?.name }}
+                                    </p>
+                                    <p v-if="currentShowFileDescription === 'true'" class="cw-block-gallery-grid-file-description">
+                                        {{ image?.attributes?.description }}
+                                    </p>
+                                </figcaption>
+                            </figure>
+                        </div>
                     </div>
-                </div>
+                </template>
             </template>
             <template v-if="canEdit" #edit>
-                <form class="default" @submit.prevent="">
-                    <label>
-                        <translate>Ordner</translate>
-                        <courseware-folder-chooser v-model="currentFolderId" allowUserFolders />
-                    </label>
-                    <label>
-                        <translate>Maximale Höhe</translate>
-                        <input type="number" min="0" max="800" v-model="currentHeight" />
-                    </label>
-                    <label>
-                        <translate>Autoplay</translate>
-                        <select v-model="currentAutoplay">
-                            <option value="true"><translate>Ja</translate></option>
-                            <option value="false"><translate>Nein</translate></option>
-                        </select>
-                    </label>
-                    <label v-if="currentAutoplay === 'true'">
-                        <translate>Autoplay Timer in Sekunden</translate>
-                        <input type="number" min="1" max="60" v-model="currentAutoplayTimer" />
-                    </label>
-                    <label v-if="currentAutoplay === 'true'">
-                        <translate>Navigation</translate>
-                        <select v-model="currentNav">
-                            <option value="true"><translate>Ja</translate></option>
-                            <option value="false"><translate>Nein</translate></option>
-                        </select>
-                    </label>
-                    <label>
-                        <translate>Dateinamen anzeigen</translate>
-                        <select v-model="currentShowFileNames">
-                            <option value="true"><translate>Ja</translate></option>
-                            <option value="false"><translate>Nein</translate></option>
-                        </select>
-                    </label>
-                    <label v-if="currentShowFileNames === 'true'">
-                        {{ $gettext('Dateiname erscheint bei Mouseover') }}
-                        <studip-tooltip-icon
-                            :text="$gettext('Der Dateiname wird angezeigt, wenn Sie den Mauszeiger über den Inhalt bewegen.')"/>
-                        <select v-model="currentMouseoverFileNames">
-                            <option value="true"><translate>Ja</translate></option>
-                            <option value="false"><translate>Nein</translate></option>
-                        </select>
-                    </label>
-                </form>
+                <courseware-tabs>
+                    <courseware-tab
+                        :index="0"
+                        :name="$gettext('Einstellungen')"
+                        :selected="true"
+                    >
+                        <form class="default" @submit.prevent="">
+                            <label>
+                                {{ $gettext('Layout') }}
+                                <select v-model="currentLayout">
+                                    <option value="carousel">{{ $gettext('Karussell') }}</option>
+                                    <option value="grid">{{ $gettext('Gitter') }}</option>
+                                </select>
+                            </label>
+                            <label>
+                                {{ $gettext('Ordner') }}
+                                <courseware-folder-chooser v-model="currentFolderId" allowUserFolders />
+                            </label>
+                            <label v-if="currentLayout === 'carousel'">
+                                {{ $gettext('Höhe') }}
+                                <input type="number" min="0" max="800" v-model="currentHeight" />
+                            </label>
+                            <label v-if="currentLayout === 'grid'">
+                                {{ $gettext('Gitter-Spalten') }}
+                                <select v-model="currentCols">
+                                    <option :value="100">1</option>
+                                    <option :value="50">2</option>
+                                    <option :value="33">3</option>
+                                    <option :value="25">4</option>
+                                    <option :value="20">5</option>
+                                </select>
+                            </label>
+                        </form>
+                    </courseware-tab>
+                    <courseware-tab
+                        :index="1"
+                        :name="$gettext('Beschreibung')"
+                    >
+                        <form class="default" @submit.prevent="">
+                            <label>
+                                {{ $gettext('Dateinamen anzeigen') }}
+                                <select v-model="currentShowFileNames">
+                                    <option value="true">{{ $gettext('Ja') }}</option>
+                                    <option value="false">{{ $gettext('Nein') }}</option>
+                                </select>
+                            </label>
+                            <label>
+                                {{ $gettext('Dateibeschreibung anzeigen') }}
+                                <select v-model="currentShowFileDescription">
+                                    <option value="true">{{ $gettext('Ja') }}</option>
+                                    <option value="false">{{ $gettext('Nein') }}</option>
+                                </select>
+                            </label>
+                            <label v-if="showDescription && currentLayout === 'carousel'">
+                                {{ $gettext('Beschreibung erscheint bei Mouseover') }}
+                                <studip-tooltip-icon
+                                    :text="$gettext('Der Beschreibungstext wird angezeigt, wenn Sie den Mauszeiger über das Bild bewegen.')"/>
+                                <select v-model="currentMouseoverFileNames">
+                                    <option value="true">{{ $gettext('Ja') }}</option>
+                                    <option value="false">{{ $gettext('Nein') }}</option>
+                                </select>
+                            </label>
+                        </form>
+                    </courseware-tab>
+                    <courseware-tab
+                        v-if="currentLayout === 'carousel'"
+                        :index="2"
+                        :name="$gettext('Autoplay')"
+                    >
+                        <form class="default" @submit.prevent="">
+                            <label>
+                                {{ $gettext('Autoplay') }}
+                                <select v-model="currentAutoplay">
+                                    <option value="true">{{ $gettext('Ja') }}</option>
+                                    <option value="false">{{ $gettext('Nein') }}</option>
+                                </select>
+                            </label>
+                            <label v-if="currentAutoplay === 'true'">
+                                {{ $gettext('Autoplay Timer in Sekunden') }}
+                                <input type="number" min="1" max="60" v-model="currentAutoplayTimer" />
+                            </label>
+                            <label v-if="currentAutoplay === 'true'">
+                                {{ $gettext('Navigation') }}
+                                <select v-model="currentNav">
+                                    <option value="true">{{ $gettext('Ja') }}</option>
+                                    <option value="false">{{ $gettext('Nein') }}</option>
+                                </select>
+                            </label>
+                        </form>
+                    </courseware-tab>
+
+                </courseware-tabs>
             </template>
             <template #info>
-                <p><translate>Informationen zum Galerie-Block</translate></p>
+                <p>{{ $gettext('Informationen zum Galerie-Block') }}</p>
             </template>
         </courseware-default-block>
     </div>
@@ -94,6 +164,8 @@
 <script>
 import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
 import CoursewareFolderChooser from './CoursewareFolderChooser.vue';
+import CoursewareTabs from './CoursewareTabs.vue';
+import CoursewareTab from './CoursewareTab.vue';
 import { blockMixin } from './block-mixin.js';
 import { mapActions, mapGetters } from 'vuex';
 
@@ -103,6 +175,8 @@ export default {
     components: {
         CoursewareDefaultBlock,
         CoursewareFolderChooser,
+        CoursewareTabs,
+        CoursewareTab,
     },
     props: {
         block: Object,
@@ -112,10 +186,13 @@ export default {
     data() {
         return {
             currentFolderId: '',
+            currentLayout: '',
             currentAutoplay: '',
             currentNav: '',
             currentHeight: '',
+            currentCols: 33,
             currentShowFileNames: '',
+            currentShowFileDescription: '',
             currentMouseoverFileNames: '',
             currentAutoplayTimer: '',
             editModeFiles: [],
@@ -132,6 +209,9 @@ export default {
         folderId() {
             return this.block?.attributes?.payload?.folder_id;
         },
+        layout() {
+            return this.block?.attributes?.payload?.layout ?? 'carousel';
+        },
         autoplay() {
             return this.block?.attributes?.payload?.autoplay;
         },
@@ -144,9 +224,15 @@ export default {
         height() {
             return this.block?.attributes?.payload?.height;
         },
+        cols() {
+            return this.block?.attributes?.payload?.cols;
+        },
         showFileNames() {
             return this.block?.attributes?.payload?.show_filenames;
         },
+        showFileDescription() {
+            return this.block?.attributes?.payload?.show_description ?? 'false';
+        },
         mouseoverFileNames() {
             return this.block?.attributes?.payload?.mouseover_filenames ?? 'false';
         },
@@ -155,6 +241,12 @@ export default {
                 return this.block?.attributes?.payload?.files;
             }
             return this.editModeFiles;
+        },
+        gridWidth() {
+            return 'calc(' + this.currentCols + '% - 8px)';
+        },
+        showDescription() {
+            return this.currentShowFileNames === 'true' || this.currentShowFileDescription === 'true';
         }
     },
     mounted() {
@@ -167,11 +259,14 @@ export default {
         }),
         initCurrentData() {
             this.currentFolderId = this.folderId;
+            this.currentLayout = this.layout;
             this.currentAutoplay = this.autoplay;
             this.currentAutoplayTimer = this.autoplayTimer;
             this.currentNav = this.nav;
             this.currentHeight = this.height;
+            this.currentCols = this.cols;
             this.currentShowFileNames = this.showFileNames;
+            this.currentShowFileDescription = this.showFileDescription;
             this.currentMouseoverFileNames = this.mouseoverFileNames;
         },
         startGallery() {
@@ -205,7 +300,8 @@ export default {
                 .map((file) => ({
                     id: file.id,
                     attributes: {
-                        name: file.attributes.name
+                        name: file.attributes.name,
+                        description: file.attributes.description
                     },
                     meta: {
                         'download-url': this.urlHelper.getURL(
@@ -228,11 +324,14 @@ export default {
             let attributes = {};
             attributes.payload = {};
             attributes.payload.folder_id = this.currentFolderId;
+            attributes.payload.layout = this.currentLayout;
             attributes.payload.autoplay = this.currentAutoplay;
             attributes.payload.autoplay_timer = this.currentAutoplayTimer;
             attributes.payload.nav = this.currentNav;
             attributes.payload.height = this.currentHeight;
+            attributes.payload.cols = this.currentCols;
             attributes.payload.show_filenames = this.currentShowFileNames;
+            attributes.payload.show_description = this.currentShowFileDescription;
             attributes.payload.mouseover_filenames = this.currentMouseoverFileNames;
 
             this.updateBlock({