diff --git a/resources/assets/javascripts/lib/wysiwyg.js b/resources/assets/javascripts/lib/wysiwyg.js
index 09ad4770c76227592296ee9f4f7d3e9f8f1986a8..1cc90e004c599c6daec55422d9d530b102a16880 100644
--- a/resources/assets/javascripts/lib/wysiwyg.js
+++ b/resources/assets/javascripts/lib/wysiwyg.js
@@ -39,6 +39,27 @@ const wysiwyg = {
 
 export default wysiwyg;
 
+const observeTextarea = (() => {
+    const observer = new MutationObserver(mutations => {
+        mutations.forEach(mutation => {
+            const editor = getEditor(mutation.target);
+            const disabledFromAttributes = mutation.target.matches('[readonly],[disabled]');
+            const disabledFromEditor = editor.isReadOnly;
+
+            if (disabledFromAttributes && !disabledFromEditor) {
+                editor.enableReadOnlyMode('studip');
+            } else if (!disabledFromAttributes && disabledFromEditor) {
+                editor.disableReadOnlyMode('studip');
+            }
+        });
+    });
+
+    return textarea => observer.observe(textarea, {
+        attributes: true,
+        attributeFilter: ['disabled', 'readonly'],
+    });
+})();
+
 async function replaceTextarea(textarea) {
     if (hasEditor(textarea)) {
         return getEditor(textarea);
@@ -54,6 +75,11 @@ async function replaceTextarea(textarea) {
     const editor = await createEditor(chunk, textarea, editorType, options);
     enhanceEditor($textarea, editor);
 
+    if ($textarea[0].matches('[readonly],[disabled]')) {
+        editor.enableReadOnlyMode('studip');
+    }
+    observeTextarea($textarea[0]);
+
     setEditor(textarea, editor);
     $textarea.trigger('load.wysiwyg');