Simple Admonitions in Astro
Add clean, professional tip, warning, danger, note, info, and caution blocks to your Astro blog with a soft stone theme and optional custom titles.
Add clean, professional, and accessible admonition blocks to your Astro site — perfect for documentation, tutorials, or blog posts.
This guide gives you:
- 6 types:
tip,warning,danger,note,info,caution - Custom titles via
[Your Title]syntax - Soft stone-themed colors (pale, desaturated, readable)
- Zero JavaScript, fully static
- No icons, minimal & elegant
Step 1: Install Required Package
1npm install remark-directiveStep 2: Create the Remark Plugin
Create remark-admonition.js in your project root:
1import { visit } from 'unist-util-visit';
2
3/** Admonition Plugin – compatible with Astro + ESM + remark-directive */
4function remarkAdmonitionCompatible() {
5 return (tree) => {
6 visit(tree, (node) => {
7 if (
8 node.type === 'containerDirective' &&
9 ['tip', 'warning', 'danger', 'note', 'info', 'caution'].includes(node.name)
10 ) {
11 const data = node.data || (node.data = {});
12 const type = node.name;
13 const titleText = type.charAt(0).toUpperCase() + type.slice(1);
14
15 // Main element: <div class="admonition admonition-tip">
16 data.hName = 'div';
17 data.hProperties = {
18 className: [`admonition`, `admonition-${type}`],
19 };
20
21 // Check if the first child is a paragraph (often contains the title)
22 const firstChild = node.children[0];
23 let titleContent = [];
24
25 if (firstChild?.type === 'paragraph') {
26 const textContent = firstChild.children
27 .filter((child) => child.type === 'text')
28 .map((child) => child.value)
29 .join('')
30 .trim();
31
32 if (textContent && !textContent.includes('\n')) {
33 titleContent = firstChild.children;
34 // Remove the first paragraph, as it is now the title
35 node.children.shift();
36 }
37 }
38
39 // If no title from content → default title
40 if (titleContent.length === 0) {
41 titleContent = [{ type: 'text', value: titleText }];
42 }
43
44 // Create title element: <p class="admonition-title">TIP</p>
45 const titleNode = {
46 type: 'paragraph',
47 data: {
48 hName: 'p',
49 hProperties: {
50 className: 'admonition-title',
51 },
52 },
53 children: titleContent,
54 };
55
56 // Insert title at the front
57 node.children.unshift(titleNode);
58 }
59 });
60 };
61}Step 3: Update astro.config.mjs
1// astro.config.mjs
2import { defineConfig } from 'astro/config';
3import remarkDirective from 'remark-directive';
4import remarkAdmonitionCompatible from './remark-admonition.js';
5
6export default defineConfig({
7 markdown: {
8 remarkPlugins: [
9 remarkDirective,
10 remarkAdmonitionCompatible,
11 ],
12 },
13});Step 4: Add Global Styles
Either add the styles to your global.css file
or create src/styles/admonitions.css and import it into your layout.
1/* src/styles/admonitions.css */
2.admonition {
3 margin: 1.5rem 0;
4 padding: 0.75rem 1rem;
5 border-left: 4px solid;
6 border-radius: 0.375rem;
7 background-color: var(--color-stone-50);
8 font-size: 0.9375rem;
9 line-height: 1.6;
10}
11
12.admonition > :first-child {
13 margin-top: 0;
14}
15
16.admonition > :last-child {
17 margin-bottom: 0;
18}
19
20.admonition p {
21 margin: 0.5rem 0;
22 color: var(--color-stone-700);
23}
24
25.admonition p:first-of-type {
26 margin-top: 0;
27}
28
29.admonition p:last-of-type {
30 margin-bottom: 0;
31}
32
33/* Title */
34.admonition-title {
35 margin: 0 0 0.5rem 0;
36 font-weight: 600;
37 font-size: 0.8125rem;
38 text-transform: uppercase;
39 letter-spacing: 0.05em;
40 color: var(--color-stone-800);
41}
42
43/* Tip – Green */
44.admonition-tip {
45 background-color: var(--color-green-100);
46 border-color: var(--color-green-300);
47 color: var(--color-green-800);
48}
49
50/* Warning – Yellow */
51.admonition-warning {
52 background-color: var(--color-yellow-100);
53 border-color: var(--color-yellow-300);
54 color: var(--color-yellow-800);
55}
56
57/* Danger – Red */
58.admonition-danger {
59 background-color: var(--color-red-100);
60 border-color: var(--color-red-300);
61 color: var(--color-red-800);
62}
63
64/* Note – Blue */
65.admonition-note {
66 background-color: var(--color-blue-100);
67 border-color: var(--color-blue-300);
68 color: var(--color-blue-800);
69}
70
71/* Info – Cyan */
72.admonition-info {
73 background-color: var(--color-cyan-100);
74 border-color: var(--color-cyan-300);
75 color: var(--color-cyan-800);
76}
77
78/* Caution – Orange */
79.admonition-caution {
80 background-color: var(--color-orange-100);
81 border-color: var(--color-orange-300);
82 color: var(--color-orange-800);
83}Import in your layout:
---
// src/layouts/BlogPost.astro
import '../styles/admonitions.css';
---Step 5: Define Color Variables (Optional but Recommended)
If you are not using Tailwind.css as I am, add these color variables to your global CSS or :root:
1:root {
2 /* Stone */
3 --color-stone-50: #fafaf9;
4 --color-stone-700: #44403c;
5 --color-stone-800: #292524;
6
7 /* Green */
8 --color-green-100: #f0fdf4;
9 --color-green-300: #86efac;
10 --color-green-800: #166534;
11
12 /* Yellow */
13 --color-yellow-100: #fefce8;
14 --color-yellow-300: #fde047;
15 --color-yellow-800: #9a3412;
16
17 /* Red */
18 --color-red-100: #fef2f2;
19 --color-red-300: #fca5a5;
20 --color-red-800: #991b1b;
21
22 /* Blue */
23 --color-blue-100: #eff6ff;
24 --color-blue-300: #93c5fd;
25 --color-blue-800: #1e40af;
26
27 /* Cyan */
28 --color-cyan-100: #ecfeff;
29 --color-cyan-300: #67e8f9;
30 --color-cyan-800: #0e7490;
31
32 /* Orange */
33 --color-orange-100: #fff7ed;
34 --color-orange-300: #fdba74;
35 --color-orange-800: #9c4221;
36}Example Usage in Markdown
1:::tip[Pro Tip]
2Use `Cmd + K` to open the command palette.
3:::
4
5:::warning
6Never commit your `.env` file.
7:::
8
9:::danger
10This action **cannot be undone**.
11:::
12
13:::note
14Astro compiles to static HTML by default.
15:::
16
17:::info[Did You Know?]
18You can use `.astro` files inside Markdown with MDX.
19:::
20
21:::caution
22This feature is experimental — test thoroughly.
23:::Result
:::tip[Pro Tip]
Use Cmd + K to open the command palette.
:::
:::warning
Never commit your .env file.
:::
:::danger This action cannot be undone. :::
:::note Astro compiles to static HTML by default. :::
:::info[Did You Know?]
You can use .astro files inside Markdown with MDX.
:::
:::caution This feature is experimental — test thoroughly. :::
Done
You now have:
- 6 flexible admonition types
- Custom titles with
[Title]syntax - Clean, stone-themed design
- Full Astro + ESM compatibility
- Zero runtime overhead
Pro tip: Want
successorexamplelater? Just add the name to the array in the plugin and a CSS rule — done.
Clean. Simple. Powerful.