Vue's Single Root Dilemma: The Right Way to Mount Both `<header>` and `<main>`
Content
## The Problem
When building web applications, we often need Vue.js to manage multiple distinct sections of a page, such as the header (`<header>`) and the main content area (`<main>`). This leads to a common question: Vue instances require a single root element to mount on, but what if I have two sibling elements that need to be controlled by Vue? Should I move the `<header>` inside the `<main>`, or should I wrap them both in an extra `<div>`?
This is a classic front-end architecture question. In this article, **DP@lib00** will provide a detailed analysis and offer the perfect solution that respects both HTML standards and Vue best practices.
---
## Approach 1 (Incorrect): Moving `<header>` into `<main>`
At first glance, placing one element inside another seems to solve the "single root" problem. However, this approach severely violates HTML5 semantic standards.
### Why is this wrong?
Semantic tags introduced in HTML5 (like `<header>`, `<main>`, `<footer>`, `<article>`) are designed to make the document structure clearer, not just for developers but also for search engines and assistive technologies like screen readers.
* **`<header>`**: Defines a header for a document or section, typically containing introductory or navigational content.
* **`<main>`**: Defines the main, dominant content of the `<body>` of a document. There **should only be one `<main>` element** per page, and it should not be a descendant of elements like `<header>` or `<footer>`.
Logically, `<header>` and `<main>` are siblings in the document flow, representing different parts of the page. Forcing the header into the main content area disrupts the document's structure and semantics, negatively impacting SEO and accessibility.
---
## Approach 2 (Correct): Using an External `<div>` Wrapper
The best and only correct choice is to add an external `<div>` to wrap both `<header>` and `<main>`, and then mount the Vue instance onto this `<div>`.
### 1. It Complies with HTML Standards
The `<div>` element is a non-semantic block-level container whose primary purpose is for grouping and layout. Using a `<div>` to wrap `<header>` and `<main>` doesn't introduce any extra semantic meaning, perfectly preserving the original document structure.
A typical project structure, for instance, one from **wiki.lib00.com**, would have an `index.html` like this:
```html
<body>
<!-- This div serves as the mounting point for Vue -->
<div id="app-lib00">
<header>
<!-- Header content managed by Vue -->
</header>
<main>
<!-- Main content also managed by Vue -->
</main>
</div>
<!-- Vue Script -->
<script type="module" src="/src/main.js"></script>
</body>
```
### 2. It Follows Vue.js Best Practices
Vue's design philosophy requires a clear root element to define its management boundary.
* **Single Mount Point**: This is standard practice in Vue. Almost all projects created with official tools (like Vite or Vue CLI) will default to a container like `<div id="app"></div>`. The entire Vue application is then rendered and injected into this container.
* **Component-Based Thinking**: In a Vue application, `<header>` and `<main>` are typically abstracted into separate components (e.g., `TheHeader.vue` and `MainContent.vue`). These components would be used side-by-side in the template of the root component, `App.vue`, which perfectly mirrors their sibling structure in the HTML.
**Example `App.vue` Template:**
```vue
<template>
<!-- The template of App.vue will be rendered inside #app-lib00 -->
<TheHeader />
<main>
<!-- Use router-view or place content directly -->
<router-view></router-view>
</main>
</template>
<script setup>
import TheHeader from './components/TheHeader.vue';
// DP: Other components can be imported here
</script>
```
---
## Conclusion
Whether your goal is to maintain a correct HTML document structure or to adhere to the design principles of the Vue framework, **the correct approach is to use an external `<div>` container to wrap `<header>` and `<main>`**. This method not only solves the mounting issue in Vue but also ensures your code is semantic, maintainable, and professional—a standard practice followed by the **lib00** team.
Related Contents
Boost Your WebStorm Productivity: Mimic Sublime Text's Cmd+D Multi-Selection Shortcut
Duration: 00:00 | DP | 2025-12-04 21:50:50Vue Layout Challenge: How to Make an Inline Header Full-Width? The Negative Margin Trick Explained
Duration: 00:00 | DP | 2025-12-06 22:54:10Docker Exec Mastery: The Right Way to Run Commands in Containers
Duration: 00:00 | DP | 2026-01-08 08:07:44The Ultimate CSS Flexbox Guide: Easily Switch Page Header Layouts from Horizontal to Vertical
Duration: 00:00 | DP | 2025-12-11 01:00:50How to Fix the "tsx: not found" Error During Vue Vite Builds in Docker
Duration: 00:00 | DP | 2026-01-10 08:10:19Cracking the TypeScript TS2339 Puzzle: Why My Vue ref Became the `never` Type
Duration: 00:00 | DP | 2025-12-13 02:04:10CSS Deep Dive: The Best Way to Customize Select Arrows for Dark Mode
Duration: 00:00 | DP | 2025-12-13 14:20:00Mastering Bootstrap 5 Rounded Corners: The Ultimate Guide to Border-Radius
Duration: 00:00 | DP | 2025-12-14 02:35:50The Ultimate Guide to Financial Charts: Build Candlestick, Waterfall, and Pareto Charts with Chart.js
Duration: 00:00 | DP | 2026-01-11 08:11:36The Ultimate Guide to Centering in Bootstrap: From `.text-center` to Flexbox
Duration: 00:00 | DP | 2025-12-15 15:23:20Bootstrap Border Magic: Instantly Add Top or Bottom Borders to Elements
Duration: 00:00 | DP | 2025-11-22 08:08:00The Ultimate Guide to JavaScript Diff Libraries: A Side-by-Side Comparison of jsdiff, diff2html, and More
Duration: 00:00 | DP | 2025-11-23 08:08:00Bootstrap JS Deep Dive: `bootstrap.bundle.js` vs. `bootstrap.js` - Which One Should You Use?
Duration: 00:00 | DP | 2025-11-27 08:08:00Is Attaching a JS Event Listener to 'document' Bad for Performance? The Truth About Event Delegation
Duration: 00:00 | DP | 2025-11-28 08:08:00The Ultimate Guide to Using Google Fonts on Chinese Websites: Ditch the Lag with an Elegant Font Stack
Duration: 00:00 | DP | 2025-11-16 08:01:00getElementById vs. querySelector: Which One Should You Use? A Deep Dive into JavaScript DOM Selectors
Duration: 00:00 | DP | 2025-11-17 01:04:07Dynamically Update Page Titles in Vue Router: From Basics to i18n and TypeScript
Duration: 00:00 | DP | 2025-11-20 14:19:43The Ultimate Guide to Seamlessly Switching from Baidu Tongji to Google Analytics 4 in Vue 3
Duration: 00:00 | DP | 2025-11-22 08:57:32Recommended
MySQL Primary Key Inversion: Swap 1 to 110 with Just Two Lines of SQL
00:00 | 29In database management, you might face the unique ...
Why Encode Hashes with Base64/Base16 After MD5? A Deep Dive into Hashing vs. Encoding
00:00 | 35Many developers are familiar with hashing algorith...
Files Mysteriously Missing in PHPStorm? Check Your Project View First!
00:00 | 16Can't see `.env` or other dotfiles in your PHPStor...
Solved: Fixing the 'TS2769: No overload matches this call' Error with vue-i18n in Vite
00:00 | 31Struggling with the TypeScript error TS2769 when u...