On Yak Shaving and md-block: A New HTML Element for Markdown

Discover how a week of yak shaving led to an elegant solution for rendering styleable Markdown in web projects

What is md-block?

md-block is a custom element (web component) created by Lea Verou that provides a zero-dependency solution for rendering markdown content in HTML. Unlike other markdown web components that use shadow DOM encapsulation, md-block renders to light DOM, making it uniquely styleable using standard CSS techniques.

This architectural choice fundamentally changes how developers interact with markdown-generated content. Because the rendered HTML appears directly in the document rather than being trapped inside shadow DOM boundaries, you can target headings, paragraphs, lists, and code blocks with regular CSS selectors. This approach eliminates the need for complex shadow DOM piercing techniques or reliance on CSS custom properties to achieve consistent styling across your site.

For web development projects that require flexible content styling, particularly documentation sites and blog platforms, this light DOM approach represents a significant advantage over alternative solutions. Our web development team specializes in building custom solutions that leverage modern web component architecture for maximum flexibility and maintainability.

The Light DOM Advantage

Understanding the difference between light DOM and shadow DOM is essential for making informed decisions about markdown rendering in your projects. When components render to shadow DOM, the resulting HTML is encapsulated within a shadow tree, effectively isolated from the rest of the document. This isolation provides style encapsulation but creates significant challenges when you want consistent styling across your entire site.

According to CSS-Tricks analysis of md-block, the light DOM approach "makes styling the output trivial compared to shadow DOM solutions." With shadow DOM rendering, developers must use CSS custom properties (CSS variables) to pass styling through the encapsulation boundary, or construct elaborate selectors that pierce through shadow DOM boundaries. Neither approach offers the flexibility developers expect from modern CSS.

md-block takes a different path entirely. When the component parses and renders markdown content, the resulting semantic HTML elements appear directly in the document tree. This means your existing CSS architecture, whether it uses CSS modules, styled-components, or plain CSS files, applies without modification. Headings inherit your typography system, links match your site's color scheme, and code blocks adopt your syntax highlighting theme automatically.

This approach proves particularly valuable for content-heavy sites like technical documentation platforms and blogs where consistent visual presentation matters deeply. Development teams can maintain a single source of truth for styling without maintaining separate theme configurations for their markdown renderer.

Zero-Dependency Architecture

One of md-block's most compelling features is its zero-dependency architecture. Unlike many markdown rendering solutions that require bundling external libraries, md-block ships as a single JavaScript module that handles all markdown parsing and rendering internally. This design philosophy eliminates common pain points in modern web development.

Traditional markdown components often depend on parsing libraries, syntax highlighters, and sometimes entire framework ecosystems. These dependencies increase bundle sizes, complicate build configurations, and introduce potential security vulnerabilities through dependency chains. Each dependency also represents a maintenance burden, as updates and security patches require ongoing attention.

md-block's single-file distribution model addresses these concerns directly. The component includes everything needed to parse CommonMark-flavored markdown and render it as semantic HTML. Built-in syntax highlighting using Prism.js means code blocks receive proper formatting without additional configuration or external scripts. This integration reduces the number of network requests, improves page load performance, and simplifies deployment pipelines.

For modern web applications built with frameworks like Next.js, this zero-dependency approach means md-block integrates seamlessly without adding bloat to your JavaScript bundle. The component works equally well in vanilla JavaScript projects, making it a versatile choice regardless of your technology stack.

Installation Options
1<!-- Option 1: Script Tag Import (simplest for quick integration) -->2<script type="module" src="https://md-block.verou.me/md-block.js"></script>3 4<!-- Option 2: ES Module Import (for modern build workflows) -->5<script type="module">6 import { MarkdownBlock, MarkdownSpan, MarkdownElement }7 from "https://md-block.verou.me/md-block.js";8</script>

The Yak Shaving Story

The term "yak shaving" describes a familiar phenomenon in software development: starting with a straightforward task only to find yourself accomplishing increasingly complex auxiliary goals, each necessary for the next, until you're far removed from where you began. The term originated from a cartoon depicting someone who, needing to shave a yak, first needed to remove its wool, which required building shears, which required mining ore, and so on indefinitely.

Lea Verou's journey toward creating md-block exemplifies this pattern perfectly. As documented on her blog, what began as a simple web component project evolved into a week-long endeavor that touched nearly every aspect of modern frontend development.

The original goal seemed modest: create a web component for an ongoing project. However, each decision revealed new requirements. The component needed to be a separate reusable library rather than project-specific code. The library required ES module support and shadow DOM compatibility. The build process needed modernization from Gulp to Rollup. The CSS architecture demanded updates from Sass to CSS variables and PostCSS. Each improvement exposed documentation gaps that couldn't be addressed without a proper markdown rendering solution.

This chain of dependencies eventually led to md-block itself - a component created to render the documentation for the original library. Only after building md-block could the documentation be completed, the library be properly documented, and the original project resume progress. Understanding this phenomenon helps web development teams recognize when building custom tools makes sense versus using existing solutions.

Basic Usage

The fundamental usage pattern for md-block is straightforward: place markdown content inside the <md-block> element, and the component handles parsing and rendering automatically. The component recognizes standard markdown syntax including headings, paragraphs, bold and italic text, lists, code blocks, and blockquotes.

After including the md-block script in your page, the custom element becomes available throughout your HTML. The component parses the markdown content within its tags and renders semantically correct HTML elements. Headings maintain proper hierarchy, paragraphs receive appropriate spacing, and code blocks automatically benefit from Prism.js syntax highlighting based on the language specified in code fences.

This simplicity makes md-block an excellent choice for content management scenarios where markdown needs to be rendered client-side. Whether you're building a documentation site, a blog platform, or any application that benefits from markdown's readability and ease of writing, md-block provides a zero-configuration solution that works immediately upon inclusion. Our web development services can help you implement markdown-based content solutions that scale with your needs.

Basic md-block Usage
1<md-block>2 # Heading Level 13 4 This is a paragraph with **bold text**, *italic text*, and ~strikethrough~.5 6 ## Code Blocks7 8 ```javascript9 function example() {10 console.log("Hello, md-block!");11 }12 ```13 14 ## Lists15 16 - List item one17 - List item two18 - List item three19</md-block>
Advanced Features

Beyond basic markdown rendering

Syntax Highlighting

Built-in Prism.js integration automatically highlights code blocks. Language is detected from code fence specifications.

Custom Heading Levels

The start-level attribute adjusts base heading level, so markdown H1s render as H2, H3, or any level you need.

External Markdown Loading

The src attribute loads markdown from external files, ideal for documentation sites with separate content files.

Auto-Linking Headings

Headings automatically receive anchor links for deep linking and navigation within your documentation.

Inline Markdown Support

The md-span companion element renders inline markdown, useful for adding formatting within HTML blocks.

Zero External Dependencies

Single-file distribution with no runtime dependencies means faster loads and simpler deployments.

Styling the Output

Because md-block renders to light DOM, styling the output uses standard CSS techniques you're already familiar with. All modern CSS features work out of the box: CSS custom properties for theming, cascade layers for style precedence, container queries for responsive styling, and any other CSS feature your project uses.

The rendered HTML follows semantic conventions, with <h1> through <h6> for headings, <p> for paragraphs, <pre> and <code> for code blocks, and <ul> or <ol> for lists. This semantic structure means your existing typographic styles apply automatically, maintaining consistency with the rest of your site.

For documentation sites built with modern web development practices, this styling flexibility enables a unified visual experience. Code blocks match your syntax highlighting theme, headings inherit your typographic scale, and links adopt your site's color scheme without additional configuration. The result is markdown content that looks native to your site rather than obviously rendered from a separate component.

Styling md-block Output
1/* Target headings specifically within md-block */2md-block h1, md-block h2, md-block h3 {3 color: #333;4 font-family: system-ui, sans-serif;5}6 7/* Style code blocks */8md-block pre {9 background: #f5f5f5;10 border-radius: 4px;11 padding: 1rem;12}13 14/* Customize links within markdown */15md-block a {16 color: #0066cc;17 text-decoration: none;18}19 20md-block a:hover {21 text-decoration: underline;22}
Comparison of Markdown Rendering Approaches
Featuremd-blockShadow DOM ComponentsFramework ComponentsStatic Site Generators
Easy StylingYes (light DOM)No (complex)VariesYes (pre-rendered)
Zero DependenciesYesVariesNoBuild-time only
Framework RequiredNoNoYesNo
Client-Side RenderingYesYesYesNo (build-time)
Syntax HighlightingBuilt-inVariesVariesBuild-time
External Content LoadingYes (src attribute)VariesVariesYes (build-time)

When to Use md-block

md-block excels in several common web development scenarios. Documentation sites benefit enormously from the ability to style markdown content to match design systems without complex theme configurations. Blog platforms can accept user-submitted markdown content knowing it will render consistently with the site's visual design. Component libraries that need to display markdown examples within their documentation can use md-block to ensure visual consistency. Static sites with dynamic content requirements, such as content loaded from a CMS or API, can render markdown client-side without build pipeline integration.

When to Consider Alternatives

Other approaches may serve certain projects better. Content-heavy sites prioritizing maximum performance might benefit from static site generators that parse markdown at build time, producing pre-rendered HTML that requires no client-side JavaScript. Projects requiring advanced markdown extensions beyond CommonMark support may need server-side parsers with extension ecosystems. Applications with strict JavaScript constraints or targeting environments where client-side rendering isn't available should use pre-rendered approaches.

Security Considerations

When rendering markdown from untrusted sources, additional security measures are essential. While md-block produces semantic HTML, it doesn't include sanitization capabilities. For user-generated content scenarios, run the rendered output through a sanitizer like DOMPurify before displaying it. This prevents potential XSS attacks from malicious markdown containing embedded scripts or other dangerous content. Following security best practices for dynamic content ensures markdown rendering enhances your application without introducing vulnerabilities.

Need Help Implementing Markdown Solutions?

Our web development team can help you integrate md-block or build custom documentation solutions tailored to your needs.

Frequently Asked Questions

Sources

  1. LeaVerou/md-block GitHub Repository - Official documentation and source code
  2. md-block.verou.me Documentation - Live demo and documentation
  3. CSS-Tricks: On Yak Shaving and md-block - Community coverage and analysis
  4. Lea Verou Blog: On Yak Shaving and md-block - Original creator's detailed account
  5. Bram.us: Render styleable Markdown with md-block - Implementation examples