diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 944742464..f9fd6eb97 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -357,9 +357,9 @@ func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byt
 		}
 		var err error
 		if n.IsChecked {
-			_, err = w.WriteString(``)
+			_, err = w.WriteString(``)
+			_, err = w.WriteString(`\n")
+		_, _ = w.WriteString("\n")
 	}
 	return ast.WalkContinue, nil
 }
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 7f27a43a7..89005fc25 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -142,9 +142,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
 
(from https://www.markdownguide.org/extended-syntax/)
 Checkboxes
 
 Definition list
 
diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go
index ba73650bd..9214a75fb 100644
--- a/modules/markup/sanitizer.go
+++ b/modules/markup/sanitizer.go
@@ -43,7 +43,7 @@ func ReplaceSanitizer() {
 
 	// Checkboxes
 	sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
-	sanitizer.policy.AllowAttrs("checked", "disabled", "readonly").OnElements("input")
+	sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
 
 	// Custom URL-Schemes
 	sanitizer.policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
@@ -66,8 +66,8 @@ func ReplaceSanitizer() {
 	// Allow classes for emojis
 	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`emoji`)).OnElements("img")
 
-	// Allow icons, checkboxes, emojis, and chroma syntax on span
-	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(ui checkbox)|(ui checked checkbox)|(emoji))$|^([a-z][a-z0-9]{0,2})$`)).OnElements("span")
+	// Allow icons, emojis, and chroma syntax on span
+	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji))$|^([a-z][a-z0-9]{0,2})$`)).OnElements("span")
 
 	// Allow generally safe attributes
 	generalSafeAttrs := []string{"abbr", "accept", "accept-charset",
diff --git a/modules/markup/sanitizer_test.go b/modules/markup/sanitizer_test.go
index 3e8dcecd5..63b70166d 100644
--- a/modules/markup/sanitizer_test.go
+++ b/modules/markup/sanitizer_test.go
@@ -40,7 +40,7 @@ func Test_Sanitizer(t *testing.T) {
 		`Ctrl + C`, `Ctrl + C`,
 		`NAUGHTY`, `NAUGHTY`,
 		``, ``,
-		``, ``,
+		`unchecked`, `unchecked`,
 		`NAUGHTY`, `NAUGHTY`,
 		`contents`, `contents`,
 	}
diff --git a/web_src/less/_markdown.less b/web_src/less/_markdown.less
index 4c8ed77cb..f931106d9 100644
--- a/web_src/less/_markdown.less
+++ b/web_src/less/_markdown.less
@@ -162,9 +162,57 @@
     list-style-type: none;
   }
 
-  li.task-list-item {
+  .task-list-item {
     list-style-type: none;
-    margin-left: calc(-2em + 2px);
+
+    input[type="checkbox"] {
+      margin: 0 6px .25em -1.6em;
+    }
+  }
+
+  .task-list-item + .task-list-item {
+    margin-top: 3px;
+  }
+
+  input[type="checkbox"] {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    position: relative;
+    border: 1px solid var(--color-secondary);
+    border-radius: 2px;
+    background: var(--color-input-background);
+    height: 14px;
+    width: 14px;
+    opacity: 1 !important; // override fomantic on edit preview
+    pointer-events: auto !important; // override fomantic on edit preview
+    vertical-align: middle !important; // override fomantic on edit preview
+  }
+
+  input[type="checkbox"]:not([disabled]):hover,
+  input[type="checkbox"]:not([disabled]):active {
+    border-color: var(--color-primary);
+  }
+
+  input[type="checkbox"]::after {
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    pointer-events: none;
+    background: var(--color-text);
+    mask-size: cover;
+  }
+
+  input[type="checkbox"]:checked::after {
+    content: "";
+    mask-image: url('data:image/svg+xml;utf8,');
+  }
+
+  input[type="checkbox"]:indeterminate::after {
+    content: "";
+    mask-image: url('data:image/svg+xml;utf8,');
   }
 
   ul ul,
@@ -422,10 +470,6 @@
     box-shadow: inset 0 -1px 0 var(--color-secondary);
   }
 
-  input[type="checkbox"] {
-    vertical-align: middle !important;
-  }
-
   .csv-data td,
   .csv-data th {
     padding: 5px;