diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.html b/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.html
index 1b6634a53e411d94bdeaa0e2b7501396d4c0273e..706cb10c053a435a882149e11414f47fd0c76e0e 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.html
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.html
@@ -9,12 +9,25 @@
        [style.padding.px]="page.margin"
        [style.background-color]="page.backgroundColor">
     <div cdkDropListGroup>
-      <div app-canvas-section class="section drop-list"
-           *ngFor="let section of page.sections; let i = index"
-           [section]="section"
-           cdkDropList cdkDropListSortingDisabled
-           (cdkDropListDropped)="elementDropped($event)" [cdkDropListData]="section">
-      </div>
+      <ng-container *ngFor="let section of page.sections; let i = index">
+        <!-- TODO split section into static and dynamic-->
+        <div *ngIf="!section.dynamicPositioning"
+             app-canvas-section class="section drop-list" id="section-{{i}}"
+             [section]="section"
+             cdkDropList cdkDropListSortingDisabled
+             [cdkDropListData]="{ sectionIndex: i }"
+             [dropListList]="dropListList"
+             (cdkDropListDropped)="elementDropped($event)"
+             [cdkDropListConnectedTo]="dropListList">
+        </div>
+        <div *ngIf="section.dynamicPositioning"
+             app-canvas-section class="section drop-list"
+             [section]="section" [sectionIndex]="i"
+             (transferElement)="moveElementBetweenSections($event.element,
+                                                           $event.previousSectionIndex,
+                                                           $event.newSectionIndex)">
+        </div>
+      </ng-container>
     </div>
   </div>
 
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.ts
index e7f48d51b5088d155f09604184aa29323e9a8d25..0b31ddd2a8560bd499bbdebb3a9316a4e786ddb5 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/page-canvas.component.ts
@@ -1,7 +1,11 @@
-import { Component, Input } from '@angular/core';
-import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
+import {
+  Component, Input, OnDestroy, OnInit
+} from '@angular/core';
+import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
 import { MatSlideToggleChange } from '@angular/material/slide-toggle';
-import { UnitPage, UnitPageSection } from '../../../../../../../common/unit';
+import { UnitPage, UnitPageSection, UnitUIElement } from '../../../../../../../common/unit';
 import { UnitService } from '../../../../unit.service';
 import { SelectionService } from '../../../../selection.service';
 
@@ -16,20 +20,64 @@ import { SelectionService } from '../../../../selection.service';
     '::ng-deep .add-section-button span.mat-button-wrapper mat-icon {vertical-align: unset}'
   ]
 })
-export class PageCanvasComponent {
+export class PageCanvasComponent implements OnInit, OnDestroy {
   @Input() page!: UnitPage;
   sectionEditMode: boolean = false;
+  dropListList: string[] = [];
+  private ngUnsubscribe = new Subject<void>();
 
   constructor(private selectionService: SelectionService, public unitService: UnitService) { }
 
-  elementDropped(event: CdkDragDrop<UnitPageSection>): void {
-    const sourceItemModel = event.item.data;
+  ngOnInit(): void {
+    this.unitService.unit
+      .pipe(takeUntil(this.ngUnsubscribe))
+      .subscribe(() => this.generateDropListList());
+  }
+
+  /*
+  To make it work that the section itself can handle drop events, but also have the canvas to handle drops
+  when outside of the section, all the allowed dropLists have to be connected. Because the lists are not properly
+  nested (see below), this needs to be done manually by IDs.
+  This list is given to the necessary dropLists to make it possible to drop items not only into them
+  but also any other connected dropLists.
+
+  Dynamic sections have droplists for the grid cells next to the actual elements. Elements can not
+  be children of the grid cells because they can span over multiple cells.
+
+  Dynamic sections don't have a general drop area, like static sections. They have grid placeholder elements
+  which are droplists. Therefore they have no parent dropList to add to the list but themselves.
+  Static elements only have the parent, which is added to the list.
+
+  Resizing in dynamic sections is handled by the section/element-overlays themselves.
+   */
+  generateDropListList(): void {
+    this.dropListList = [];
+    this.page.sections.forEach((section: UnitPageSection, index: number) => {
+      if (!section.dynamicPositioning) {
+        this.dropListList.push(`section-${index}`);
+      } else {
+        section.gridColumnSizes.split(' ').forEach((columnSize: string, columnIndex: number) => {
+          section.gridRowSizes.split(' ').forEach((rowSize: string, rowIndex: number) => {
+            this.dropListList.push(`list-${index}-${columnIndex + 1}-${rowIndex + 1}`); // grid starts counting at 1
+          });
+        });
+      }
+    });
+  }
+
+  moveElementBetweenSections(element: UnitUIElement, previousSectionIndex: number, newSectionIndex: number): void {
+    this.unitService.transferElement([element],
+      this.page.sections[previousSectionIndex],
+      this.page.sections[newSectionIndex]);
+  }
+
+  elementDropped(event: CdkDragDrop<DropListData>): void {
+    const sourceItemModel = (event.item.data as DragItemData).element;
 
     if (event.previousContainer !== event.container) {
-      transferArrayItem(event.previousContainer.data.elements,
-        event.container.data.elements,
-        event.previousIndex,
-        event.currentIndex);
+      this.moveElementBetweenSections(event.item.data.element,
+        event.previousContainer.data.sectionIndex,
+        event.container.data.sectionIndex);
     } else {
       let newXPosition = sourceItemModel.xPosition + event.distance.x;
       if (newXPosition < 0) {
@@ -72,4 +120,19 @@ export class PageCanvasComponent {
     moveItemInArray(this.page.sections, event.previousIndex, event.currentIndex);
     this.unitService.setPageSections(this.page, this.page.sections);
   }
+
+  ngOnDestroy(): void {
+    this.ngUnsubscribe.next();
+    this.ngUnsubscribe.complete();
+  }
+}
+
+export interface DragItemData {
+  dragType: string;
+  element: UnitUIElement;
+}
+
+export interface DropListData {
+  sectionIndex: number;
+  gridCoordinates?: number[];
 }
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/section.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/section.component.ts
index 3be5f06d19dd6d2a644761be021d547f14aedd99..70d7122ae8233468716ddae638c86dcb161788d8 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/section.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/section.component.ts
@@ -1,8 +1,11 @@
-import { Component, Input } from '@angular/core';
+import {
+  Component, Input, Output, EventEmitter
+} from '@angular/core';
 import { CdkDragDrop } from '@angular/cdk/drag-drop/drag-events';
-import { UnitPageSection } from '../../../../../../../common/unit';
+import { UnitPageSection, UnitUIElement } from '../../../../../../../common/unit';
 import { UnitService } from '../../../../unit.service';
 import { SelectionService } from '../../../../selection.service';
+import { DragItemData, DropListData } from './page-canvas.component';
 
 @Component({
   selector: '[app-canvas-section]',
@@ -27,6 +30,8 @@ import { SelectionService } from '../../../../selection.service';
            [style.height.%]="100"
            cdkDropListGroup>
 
+        <!-- Dynamic sections have the droplists for the grid cells next to the actual elements. Elements can not
+             be children of the grid cells because they can span over multiple cells. -->
         <ng-container *ngFor="let column of this.section.gridColumnSizes.split(' '); let x = index">
           <ng-container *ngFor="let row of this.section.gridRowSizes.split(' '); let y = index">
             <div class="grid-placeholder"
@@ -34,7 +39,9 @@ import { SelectionService } from '../../../../selection.service';
                  [style.grid-column-end]="x + 1"
                  [style.grid-row-start]="y + 1"
                  [style.grid-row-end]="y + 1"
-                 cdkDropList [cdkDropListData]="[x + 1, y + 1]" (cdkDropListDropped)="drop($event)">
+                 cdkDropList [cdkDropListData]="{ sectionIndex: sectionIndex, gridCoordinates: [x + 1, y + 1] }"
+                 (cdkDropListDropped)="drop($any($event))"
+                 id="list-{{sectionIndex}}-{{x+1}}-{{y+1}}">
               {{x + 1}} / {{y + 1}}
             </div>
           </ng-container>
@@ -53,6 +60,8 @@ import { SelectionService } from '../../../../selection.service';
                                     [style.grid-row-start]="element.gridRowStart"
                                     [style.grid-row-end]="element.gridRowEnd"
                                     cdkDropList cdkDropListSortingDisabled
+                                    [cdkDropListData]="{ sectionIndex: sectionIndex }"
+                                    [cdkDropListConnectedTo]="dropListList"
                                     (resize)="resizeOverlay($event)"
                                     [style.pointer-events]="dragging ? 'none' : 'auto'"
                                     [style.position]="dragging ? 'absolute' : null"
@@ -103,6 +112,12 @@ import { SelectionService } from '../../../../selection.service';
 export class SectionComponent {
   @Input() section!: UnitPageSection;
   @Input() sectionEditMode: boolean = false;
+  @Input() sectionIndex!: number;
+  @Input() dropListList!: string[];
+  @Output() transferElement = new EventEmitter<{ element: UnitUIElement,
+    previousSectionIndex: number,
+    newSectionIndex: number }>();
+
   selected = true;
   dragging = false;
   draggingElementWidth: number | undefined = 0;
@@ -110,34 +125,46 @@ export class SectionComponent {
 
   constructor(public selectionService: SelectionService, public unitService: UnitService) { }
 
-  drop(event: CdkDragDrop<number[]>): void {
-    if (event.item.data.dragType === 'move') {
+  drop(event: CdkDragDrop<DropListData>): void {
+    const dragItemData: DragItemData = event.item.data;
+
+    // Move element to other section - handled by parent (page-canvas).
+    if (event.previousContainer.data.sectionIndex !== event.container.data.sectionIndex) {
+      this.transferElement.emit({
+        element: event.item.data.element,
+        previousSectionIndex: event.previousContainer.data.sectionIndex,
+        newSectionIndex: event.container.data.sectionIndex
+      });
+    }
+    if (dragItemData.dragType === 'move') {
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridColumnStart', event.container.data[0]
+        [event.item.data.element],
+        'gridColumnStart', event.container.data.gridCoordinates![0]
       );
       // Ensure the end value is at least the same as the start, otherwise the grid breaks
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridColumnEnd', Math.max(event.item.data.element.gridColumnEnd, event.container.data[0])
+        [dragItemData.element],
+        'gridColumnEnd', Math.max(event.item.data.element.gridColumnEnd, event.container.data.gridCoordinates![0])
       );
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridRowStart', event.container.data[1]
+        [dragItemData.element],
+        'gridRowStart', event.container.data.gridCoordinates![1]
       );
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridRowEnd', Math.max(event.item.data.element.gridRowEnd, event.container.data[1])
+        [dragItemData.element],
+        'gridRowEnd', Math.max(event.item.data.element.gridRowEnd, event.container.data.gridCoordinates![1])
       );
-    } else { // resize
+    } else if (event.item.data.dragType === 'resize') { // resize
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridColumnEnd', event.container.data[0] + 1
+        [dragItemData.element],
+        'gridColumnEnd', event.container.data.gridCoordinates![0] + 1
       );
       this.unitService.updateElementProperty(
-        this.selectionService.getSelectedElements(),
-        'gridRowEnd', event.container.data[1] + 1
+        [dragItemData.element],
+        'gridRowEnd', event.container.data.gridCoordinates![1] + 1
       );
+    } else {
+      throw new Error('Unknown drop event');
     }
   }
 
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts
index b70c6dea16dbb49584d9f8a3db240942be74207b..aa85692f64e7fa09ac9643730dc5a116b7c159c7 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts
@@ -7,7 +7,7 @@ import { CanvasElementOverlay } from './canvas-element-overlay';
   template: `
     <!--    Needs extra div because styling can interfere with drag and drop-->
     <div class="draggable-element" [class.draggable-element-selected]="selected"
-         cdkDrag [cdkDragData]="this.element"
+         cdkDrag [cdkDragData]="{dragType: 'move', element: element}"
          (click)="selectElement($event.shiftKey)" (cdkDragStarted)="selectElement()"
          (dblclick)="openEditDialog()">
       <div [style.position]="'absolute'"
diff --git a/projects/editor/src/app/unit.service.ts b/projects/editor/src/app/unit.service.ts
index 8ff3d2611bbb944f8ca64b89829f3718e6d49bfd..042b58853435045443dc0559ea41ae95045b3d93 100644
--- a/projects/editor/src/app/unit.service.ts
+++ b/projects/editor/src/app/unit.service.ts
@@ -151,6 +151,14 @@ export class UnitService {
     this.veronaApiService.sendVoeDefinitionChangedNotification();
   }
 
+  /* Move element between sections */
+  transferElement(elements: UnitUIElement[], previousSection: UnitPageSection, newSection: UnitPageSection): void {
+    previousSection.elements = previousSection.elements.filter(element => !elements.includes(element));
+    elements.forEach(element => newSection.elements.push(element));
+    this._unit.next(this._unit.value);
+    this.veronaApiService.sendVoeDefinitionChangedNotification();
+  }
+
   duplicateElementsInSection(elements: UnitUIElement[], section: UnitPageSection): void {
     elements.forEach((element: UnitUIElement) => {
       const newElement: UnitUIElement = { ...element };
@@ -224,6 +232,7 @@ export class UnitService {
       section[property] = value;
     }
     this.elementPropertyUpdated.next();
+    this._unit.next(this._unit.value);
     this.veronaApiService.sendVoeDefinitionChangedNotification();
   }