diff --git a/changes/changelog.d/1121.enhancement b/changes/changelog.d/1121.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..188865c94c8486d59970809e3728d6fe0d878e41
--- /dev/null
+++ b/changes/changelog.d/1121.enhancement
@@ -0,0 +1 @@
+Use semantic headers for accessibility (#1121)
\ No newline at end of file
diff --git a/front/package.json b/front/package.json
index 4a85f6469ebb2d6ab2898f7586f6eb9b7d5b30b1..86540e14969a2f9d4e9ef7954d50423071c093af 100644
--- a/front/package.json
+++ b/front/package.json
@@ -20,6 +20,7 @@
     "core-js": "^3.6.4",
     "diff": "^4.0.1",
     "django-channels": "^1.1.6",
+    "focus-trap": "^5.1.0",
     "fomantic-ui-css": "^2.8.3",
     "howler": "^2.0.14",
     "js-logger": "^1.4.1",
diff --git a/front/src/components/Queue.vue b/front/src/components/Queue.vue
index 4becb11f3cb1fda84053d458f5015389935fb43b..0813291af5e89ed1325a4d3713765ca76045efa8 100644
--- a/front/src/components/Queue.vue
+++ b/front/src/components/Queue.vue
@@ -209,7 +209,7 @@ import $ from 'jquery'
 import moment from "moment"
 import lodash from '@/lodash'
 import time from "@/utils/time"
-
+import createFocusTrap from 'focus-trap'
 import store from "@/store"
 
 export default {
@@ -224,11 +224,14 @@ export default {
       showVolume: false,
       isShuffling: false,
       tracksChangeBuffer: null,
+      focusTrap: null,
       time
     }
   },
   mounted () {
     let self = this
+    this.focusTrap = createFocusTrap(this.$el, {allowOutsideClick: () => { return true }})
+    this.focusTrap.activate()
     this.$nextTick(() => {
       setTimeout(() => {
         this.scrollToCurrent()
diff --git a/front/src/components/SetInstanceModal.vue b/front/src/components/SetInstanceModal.vue
index 618a16a20df016ae33facfa4074fe9e4c1ba26b9..2e5c24bc2acf72eaeec2cb1a6ad2dd5a0c2b8ffb 100644
--- a/front/src/components/SetInstanceModal.vue
+++ b/front/src/components/SetInstanceModal.vue
@@ -35,7 +35,7 @@
       </form>
     </div>
     <div class="actions">
-      <div class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></div>
+      <button class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></button>
     </div>
   </modal>
 </template>
diff --git a/front/src/components/ShortcutsModal.vue b/front/src/components/ShortcutsModal.vue
index 017cdc977f7a790c5e687bede808f4860f2b67d4..c88bfb71591053623ae7038d6ff55f68a7bd9a86 100644
--- a/front/src/components/ShortcutsModal.vue
+++ b/front/src/components/ShortcutsModal.vue
@@ -36,7 +36,7 @@
       </div>
     </section>
     <footer class="actions">
-      <div class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Close</translate></div>
+      <button class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Close</translate></button>
     </footer>
   </modal>
 </template>
diff --git a/front/src/components/auth/LoginForm.vue b/front/src/components/auth/LoginForm.vue
index 3b18fbc290ed34427e3a523b4705870e6f6f78b1..f0591a5385d36c59dd64fc556c5e5fe6ccb03abe 100644
--- a/front/src/components/auth/LoginForm.vue
+++ b/front/src/components/auth/LoginForm.vue
@@ -25,7 +25,6 @@
         </label>
         <input
         ref="username"
-        tabindex="1"
         required
         name="username"
         type="text"
@@ -50,7 +49,7 @@
         <translate translate-context="Contant/Auth/Paragraph" :translate-params="{domain: $store.getters['instance/domain']}">You will be redirected to %{ domain } to authenticate.</translate>
       </p>
     </template>
-    <button tabindex="3" :class="['ui', {'loading': isLoading}, 'right', 'floated', buttonClasses, 'button']" type="submit">
+    <button :class="['ui', {'loading': isLoading}, 'right', 'floated', buttonClasses, 'button']" type="submit">
       <translate translate-context="*/Login/*/Verb">Login</translate>
     </button>
   </form>
diff --git a/front/src/components/common/DangerousButton.vue b/front/src/components/common/DangerousButton.vue
index 353c8ecf339fb96f943dc75ff2b11d6e61ed8b03..763f3fa98bcdd10160f7499266b03addcffdf871 100644
--- a/front/src/components/common/DangerousButton.vue
+++ b/front/src/components/common/DangerousButton.vue
@@ -14,14 +14,14 @@
         </div>
       </div>
       <div class="actions">
-        <div class="ui basic cancel button">
+        <button class="ui basic cancel button">
           <translate translate-context="*/*/Button.Label/Verb">Cancel</translate>
-        </div>
-        <div :class="['ui', 'confirm', confirmButtonColor, 'button']" @click="confirm">
+        </button>
+        <button :class="['ui', 'confirm', confirmButtonColor, 'button']" @click="confirm">
           <slot name="modal-confirm">
             <translate translate-context="Modal/*/Button.Label/Short, Verb">Confirm</translate>
           </slot>
-        </div>
+        </button>
       </div>
     </modal>
   </div>
diff --git a/front/src/components/moderation/FilterModal.vue b/front/src/components/moderation/FilterModal.vue
index 2c650014c8b71049b7e99b84f7a2a701f7a0fd8f..f83e69741bd325d17ba095313634bc78788cf87d 100644
--- a/front/src/components/moderation/FilterModal.vue
+++ b/front/src/components/moderation/FilterModal.vue
@@ -37,8 +37,8 @@
       </div>
     </div>
     <div class="actions">
-      <div class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></div>
-      <div :class="['ui', 'success', {loading: isLoading}, 'button']" @click="hide"><translate translate-context="Popup/*/Button.Label">Hide content</translate></div>
+      <button class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></button>
+      <button :class="['ui', 'success', {loading: isLoading}, 'button']" @click="hide"><translate translate-context="Popup/*/Button.Label">Hide content</translate></button>
     </div>
   </modal>
 </template>
diff --git a/front/src/components/moderation/ReportModal.vue b/front/src/components/moderation/ReportModal.vue
index db37960a27970ea52c2f9d90f301e579a8be615a..f32f7b6f6f0aa52c3e7527372524be1654d9a5de 100644
--- a/front/src/components/moderation/ReportModal.vue
+++ b/front/src/components/moderation/ReportModal.vue
@@ -71,7 +71,7 @@
       </div>
     </div>
     <div class="actions">
-      <div class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></div>
+      <button class="ui basic cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate></button>
       <button
         v-if="canSubmit"
         :class="['ui', 'success', {loading: isLoading}, 'button']"
diff --git a/front/src/components/semantic/Modal.vue b/front/src/components/semantic/Modal.vue
index 78f9534213eddd6d55adbbb89030ac896b640e63..0a93a053ed3f34652ed9092639f58713e3358e13 100644
--- a/front/src/components/semantic/Modal.vue
+++ b/front/src/components/semantic/Modal.vue
@@ -9,6 +9,7 @@
 
 <script>
 import $ from 'jquery'
+import createFocusTrap from 'focus-trap'
 
 export default {
   props: {
@@ -17,9 +18,13 @@ export default {
   },
   data () {
     return {
-      control: null
+      control: null,
+      focusTrap: null,
     }
   },
+  mounted () {
+    this.focusTrap = createFocusTrap(this.$el)
+  },
   beforeDestroy () {
     if (this.control) {
       $(this.$el).modal('hide')
@@ -38,6 +43,11 @@ export default {
         }.bind(this),
         onHidden: function () {
           this.$emit('update:show', false)
+          this.focusTrap.pause()
+        }.bind(this),
+        onVisible: function () {
+          this.focusTrap.activate()
+          this.focusTrap.unpause()
         }.bind(this)
       })
     }
diff --git a/front/yarn.lock b/front/yarn.lock
index 40aa5b9d00c10356d2c6ba8622a62a0fd9f5a1f8..4cab2dee136f89a7c816672ee6587db121c84fd1 100644
--- a/front/yarn.lock
+++ b/front/yarn.lock
@@ -4375,6 +4375,14 @@ flush-write-stream@^1.0.0:
     inherits "^2.0.3"
     readable-stream "^2.3.6"
 
+focus-trap@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-5.1.0.tgz#64a0bfabd95c382103397dbc96bfef3a3cf8e5ad"
+  integrity sha512-CkB/nrO55069QAUjWFBpX6oc+9V90Qhgpe6fBWApzruMq5gnlh90Oo7iSSDK7pKiV5ugG6OY2AXM5mxcmL3lwQ==
+  dependencies:
+    tabbable "^4.0.0"
+    xtend "^4.0.1"
+
 follow-redirects@1.5.10:
   version "1.5.10"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
@@ -9206,6 +9214,11 @@ symbol-tree@^3.2.2:
   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
   integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
 
+tabbable@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261"
+  integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==
+
 table@^5.2.3:
   version "5.4.6"
   resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"