Skip to main content

CSS-only Tailwind CSS diff viewer for side-by-side content comparison with a draggable divider. No JavaScript required. WCAG AA accessible, works with Django, HTMX, Laravel, React, and any stack.

Diff components display differences between two versions of content, ideal for showing code changes, document revisions, or comparison views. Built with semantic HTML and color-coded styling, diffs help users understand what changed. The Frutjam diff system supports multiple types and stylesโ€”perfect for version control interfaces, revision history, and change tracking.

CSS-only, no JavaScript required. WCAG AA accessible and framework-agnostic โ€” works with Django, HTMX, Laravel, React, and any stack.

Class Type Description
diffBaseSide-by-side comparison container with a draggable divider
diff-item-1ModifierLeft (before) pane of the comparison
diff-item-2ModifierRight (after) pane of the comparison
diff-resizerModifierDraggable handle to resize the two panes

Basic Usage

Create a simple side-by-side diff with before and after states.

Before
After
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<figure class="diff aspect-video" tabindex="0" aria-label="Before and after comparison">
  <div class="diff-item-1" aria-label="Before">
    <div class="bg-base-100 grid place-items-center text-4xl font-bold">
      Before
    </div>
  </div>
  <div class="diff-item-2" aria-label="After">
    <div class="bg-base-200 grid place-items-center text-4xl font-bold">
      After
    </div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<figure className="diff aspect-video" tabindex="0" aria-label="Before and after comparison">
  <div className="diff-item-1" aria-label="Before">
    <div className="bg-base-100 grid place-items-center text-4xl font-bold">
      Before
    </div>
  </div>
  <div className="diff-item-2" aria-label="After">
    <div className="bg-base-200 grid place-items-center text-4xl font-bold">
      After
    </div>
  </div>
  <div className="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<figure class="diff aspect-video" tabindex="0" aria-label="Before and after comparison">
  <div class="diff-item-1" aria-label="Before">
    <div class="bg-base-100 grid place-items-center text-4xl font-bold">
      Before
    </div>
  </div>
  <div class="diff-item-2" aria-label="After">
    <div class="bg-base-200 grid place-items-center text-4xl font-bold">
      After
    </div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

Diff Text Comparison

Display code or text changes side-by-side for detailed comparison.

const greeting = "Hello";
console.log(greeting);
let count = 0;
const greeting = "Hello World";
console.log(greeting);
let count = 1;
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<figure class="diff aspect-video" tabindex="0" aria-label="Code comparison: before and after changes">
  <div class="diff-item-1" aria-label="Before: original code">
    <div class="bg-base-100 p-4">
    <pre>const greeting = "Hello";
console.log(greeting);
let count = 0;</pre>
    </div>
  </div>
  <div class="diff-item-2" aria-label="After: updated code">
    <div class="bg-base-200 p-4">
    <pre>const greeting = "Hello World";
console.log(greeting);
let count = 1;</pre>
    </div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

Diff with Color Coding

Use semantic colors to highlight removed, added, or changed content.

- const old = "value";
+ const updated = "value";
html
1
2
3
4
5
6
7
8
9
<figure class="diff aspect-video" tabindex="0" aria-label="Color-coded diff: removed and added lines">
  <div class="diff-item-1" aria-label="Removed line">
    <div class="bg-error text-on-error p-4 font-mono">- const old = "value";</div>
  </div>
  <div class="diff-item-2" aria-label="Added line">
    <div class="bg-success text-on-success p-4 font-mono">+ const updated = "value";</div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

Image Comparison

Compare visual changes between before and after images with draggable resizer.

Original color photo
Grayscale version of the same photo
html
1
2
3
4
5
6
7
8
9
<figure class="diff aspect-video" tabindex="0" aria-label="Image comparison: color versus grayscale">
  <div class="diff-item-1" aria-label="Before: color version">
    <img src="https://cdn.frutjam.com/images/photo-5.jpg?format=webp&width=800&height=450" alt="Original color photo" loading="lazy">
  </div>
  <div class="diff-item-2" aria-label="After: grayscale version">
    <img src="https://cdn.frutjam.com/images/photo-5.jpg?format=webp&saturation=-100&width=800&height=450" alt="Grayscale version of the same photo" loading="lazy">
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

Diff Sizes

Control the diff size using width and height utilities on the container.

Small
Diff
Medium
Diff
Large
Diff
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<figure class="diff aspect-video w-64" tabindex="0" aria-label="Small diff comparison">
  <div class="diff-item-1" aria-label="Before">
    <div class="bg-base-200 grid place-items-center text-base font-bold">Small</div>
  </div>
  <div class="diff-item-2" aria-label="After">
    <div class="bg-base-100 grid place-items-center text-base font-bold">Diff</div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

<figure class="diff aspect-video w-96" tabindex="0" aria-label="Medium diff comparison">
  <div class="diff-item-1" aria-label="Before">
    <div class="bg-base-200 grid place-items-center text-2xl font-bold">Medium</div>
  </div>
  <div class="diff-item-2" aria-label="After">
    <div class="bg-base-100 grid place-items-center text-2xl font-bold">Diff</div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>

<figure class="diff aspect-video w-full" tabindex="0" aria-label="Large diff comparison">
  <div class="diff-item-1" aria-label="Before">
    <div class="bg-primary text-on-primary grid place-items-center text-4xl font-bold">Large</div>
  </div>
  <div class="diff-item-2" aria-label="After">
    <div class="bg-secondary text-on-secondary grid place-items-center text-4xl font-bold">Diff</div>
  </div>
  <div class="diff-resizer" role="slider" aria-label="Comparison slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0"></div>
</figure>