<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Seppe Gadeyne</title>
    <description>The latest articles on DEV Community by Seppe Gadeyne (@seppegadeyne).</description>
    <link>https://dev.to/seppegadeyne</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F412443%2Fb770a129-9311-40ef-92f1-7cff76ed7c72.jpeg</url>
      <title>DEV Community: Seppe Gadeyne</title>
      <link>https://dev.to/seppegadeyne</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seppegadeyne"/>
    <language>en</language>
    <item>
      <title>Set up Astro with Svelte, Tailwind CSS, Vercel, Prettier, and TypeScript</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Thu, 10 Sep 2026 09:32:10 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/set-up-astro-with-svelte-tailwind-css-vercel-prettier-and-typescript-7m0</link>
      <guid>https://dev.to/seppegadeyne/set-up-astro-with-svelte-tailwind-css-vercel-prettier-and-typescript-7m0</guid>
      <description>&lt;p&gt;I use Astro with Svelte for interactive components, Tailwind CSS for styling, and Prettier to keep formatting consistent. This guide walks through the project setup, strict TypeScript checks, and a static deployment to Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Before you begin, make sure you have the following on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 22.12.0 or higher (odd-numbered releases are not supported)&lt;/li&gt;
&lt;li&gt;Visual Studio Code with these extensions: astro-vscode, prettier-vscode, svelte-vscode, and tailwindcss-intellisense&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. Astro needs no global CLI and no Docker container to get going.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Astro project setup
&lt;/h2&gt;

&lt;p&gt;Create a new Astro project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create astro@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Astro asks where to create the project and which starter to use. Choose a minimal template unless you already need a themed starter, and keep the strict TypeScript configuration shown below. That gives you a clean setup without demo files to remove later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Svelte, Tailwind CSS, Prettier, and type checks
&lt;/h2&gt;

&lt;p&gt;From inside the newly created project folder, add the integrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx astro add svelte
npx astro add tailwind
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @astrojs/check typescript prettier prettier-plugin-astro prettier-plugin-svelte prettier-plugin-tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tailwind's integration has changed. The &lt;code&gt;npx astro add tailwind&lt;/code&gt; command now installs the Tailwind Vite plugin (&lt;code&gt;@tailwindcss/vite&lt;/code&gt;), which is the recommended path for Tailwind 4. The integration commands update &lt;code&gt;astro.config.mjs&lt;/code&gt; where needed, so you rarely have to configure them by hand. Accept the defaults when prompted.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/styles/global.css&lt;/code&gt; with &lt;code&gt;@import "tailwindcss";&lt;/code&gt; if the command has not already created it. Import that stylesheet in your shared Astro layout frontmatter with &lt;code&gt;import '../styles/global.css'&lt;/code&gt; (adjust the relative path). The Vite plugin alone does not apply styles to a page.&lt;/p&gt;

&lt;p&gt;Why this stack? Astro renders pages to static HTML by default and only ships JavaScript where an island needs it. That helps keep a &lt;a href="https://straffesites.com/en/glossary/static-website" rel="noopener noreferrer"&gt;static website&lt;/a&gt; fast. I use Svelte 5 for interactive parts because it has a small runtime, runes-based reactivity, and a comfortable component model. Tailwind CSS provides utility classes and can encode the tokens from a &lt;a href="https://straffesites.com/en/glossary/design-system" rel="noopener noreferrer"&gt;design system&lt;/a&gt;, keeping the styling predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Prettier
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;.prettierrc&lt;/code&gt; file in the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"semi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tailwindStylesheet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/styles/global.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-astro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-svelte"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.prettierignore&lt;/code&gt; too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/**
vercel.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details matter in 2026. First, &lt;code&gt;pluginSearchDirs&lt;/code&gt; is gone. Prettier 3 no longer discovers plugins implicitly, so you must list them in &lt;code&gt;plugins&lt;/code&gt;. Second, &lt;code&gt;prettier-plugin-tailwindcss&lt;/code&gt; sorts classes for both Tailwind 3 and 4 configurations. With Tailwind 4, &lt;code&gt;tailwindStylesheet&lt;/code&gt; is required: point it at your actual CSS entry file, here &lt;code&gt;src/styles/global.css&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Astro
&lt;/h2&gt;

&lt;p&gt;A typical &lt;code&gt;astro.config.mjs&lt;/code&gt; for this stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;astro/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@astrojs/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;tailwindcss&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tailwindcss/vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;site&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;vite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;trailingSlash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Astro's default output is static, and a fully static site can deploy to Vercel without an adapter. The platform serves the exported HTML and assets from its CDN without per-request rendering. Run &lt;code&gt;npx astro add vercel&lt;/code&gt; only when you need on-demand routes or Vercel-specific services such as image optimization; current versions import the adapter from &lt;code&gt;@astrojs/vercel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;astro check&lt;/code&gt; command type-checks &lt;code&gt;.astro&lt;/code&gt; files. It requires &lt;code&gt;@astrojs/check&lt;/code&gt; and TypeScript, which the install command above adds. Run it in CI to catch type errors before they are merged or deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"astro dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"check"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"astro check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"astro check &amp;amp;&amp;amp; astro build"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring TypeScript
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"astro/tsconfigs/strict"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;".astro/types.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;paths&lt;/code&gt; setting gives you path aliases: import components as &lt;code&gt;@/components/Button.astro&lt;/code&gt; instead of &lt;code&gt;../../components/Button.astro&lt;/code&gt;. My site uses the same trick with &lt;code&gt;@blocks/*&lt;/code&gt; for its block registry.&lt;/p&gt;

&lt;p&gt;The old advice to declare a &lt;code&gt;*.astro&lt;/code&gt; module shim in &lt;code&gt;src/env.d.ts&lt;/code&gt; is obsolete. Since version 3, Astro has generated typed references for &lt;code&gt;.astro&lt;/code&gt; imports automatically. If you still have such a declaration lying around, you can delete it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Vercel
&lt;/h2&gt;

&lt;p&gt;A static deployment needs little configuration after you connect the repository in Vercel. Here is a minimal &lt;code&gt;vercel.json&lt;/code&gt; for the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"regions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"fra1"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cleanUrls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trailingSlash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"redirects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/old-slug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/new-slug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"permanent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;trailingSlash: false&lt;/code&gt; makes Vercel redirect &lt;code&gt;/old-slug/&lt;/code&gt; to &lt;code&gt;/old-slug&lt;/code&gt; with a 308, which keeps your URLs canonical. When you migrate slugs, account for both trailing-slash variants so every old incoming link reaches the intended page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the project
&lt;/h2&gt;

&lt;p&gt;Start the development server with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the project behaves oddly after an Astro upgrade, reinstall the dependencies before rewriting your configuration. Stale dependency state is often the culprit.&lt;/p&gt;




&lt;p&gt;Originally published on &lt;a href="https://straffesites.com/en/blog/astro-setup-svelte-tailwindcss-vercel-prettier-typescript" rel="noopener noreferrer"&gt;Straffe Sites&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>svelte</category>
      <category>tailwindcss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Integrate Prettier with Astro and Tailwind CSS</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Mon, 07 Sep 2026 08:53:55 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/integrate-prettier-with-astro-and-tailwind-css-58ig</link>
      <guid>https://dev.to/seppegadeyne/integrate-prettier-with-astro-and-tailwind-css-58ig</guid>
      <description>&lt;p&gt;Prettier handles indentation, quotes, and line breaks. With the right plugins, it also formats &lt;code&gt;.astro&lt;/code&gt; files and sorts Tailwind utility classes. This guide sets up both for an &lt;a href="https://straffesites.com/en/glossary/astro" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; project using Prettier 3 and Tailwind CSS 4.&lt;/p&gt;

&lt;p&gt;There are two details to get right: Prettier 3 requires explicit plugin loading, and the Tailwind plugin needs the CSS entry point for your Tailwind 4 configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Use a current Node.js LTS release supported by your Astro version, with npm installed. If you use VS Code, install these extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; (&lt;code&gt;astro-build.astro-vscode&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; (&lt;code&gt;esbenp.prettier-vscode&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Optional: &lt;a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss" rel="noopener noreferrer"&gt;Tailwind CSS IntelliSense&lt;/a&gt; for class suggestions; it is not required for formatting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you do not have an Astro project yet, create one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create astro@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose a starter template and install its dependencies when prompted. Run the remaining commands from the project folder created by the wizard. This guide assumes Astro 5.2 or newer, where &lt;code&gt;astro add tailwind&lt;/code&gt; installs the Tailwind 4 Vite plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Tailwind CSS and Prettier
&lt;/h2&gt;

&lt;p&gt;If Tailwind 4 is not already configured, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx astro add tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review and accept the proposed changes. The command adds &lt;code&gt;@tailwindcss/vite&lt;/code&gt; to &lt;code&gt;astro.config.mjs&lt;/code&gt; and creates &lt;code&gt;src/styles/global.css&lt;/code&gt; with the Tailwind import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'tailwindcss'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import that stylesheet in the front matter of a shared layout, such as &lt;code&gt;src/layouts/Layout.astro&lt;/code&gt;, or in each page that needs it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import '../styles/global.css'
---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merge the import into your existing front matter; keep the rest of the layout. The CSS must be imported by a layout or page you actually render. See &lt;a href="https://docs.astro.build/en/guides/styling/#add-tailwind-4" rel="noopener noreferrer"&gt;Astro's Tailwind setup instructions&lt;/a&gt; if your project uses a different structure. Existing Tailwind 3 projects should follow the migration instructions there first.&lt;/p&gt;

&lt;p&gt;Then install Prettier and both formatting plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; prettier@3 prettier-plugin-astro prettier-plugin-tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--save-exact&lt;/code&gt; saves exact versions in &lt;code&gt;package.json&lt;/code&gt;. Commit &lt;code&gt;package-lock.json&lt;/code&gt; as well so teammates and CI can install the same dependency tree with &lt;code&gt;npm ci&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Prettier
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.prettierrc&lt;/code&gt; in the project root, or merge these settings into your existing Prettier configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"semi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-astro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tailwindStylesheet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/styles/global.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.astro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"astro"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first five options are formatting preferences, not Astro requirements. Adjust them to your team's conventions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;plugins&lt;/code&gt; array explicitly loads the plugins. &lt;a href="https://prettier.io/blog/2023/07/05/3.0.0#plugin-search-feature-has-been-removed-14759-by-fisker" rel="noopener noreferrer"&gt;Prettier 3 removed automatic plugin discovery&lt;/a&gt;; installing a package alone does not load it in the CLI. The Astro parser override follows the &lt;a href="https://github.com/withastro/prettier-plugin-astro#recommended-configuration" rel="noopener noreferrer"&gt;Astro plugin's recommended configuration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For Tailwind 4, &lt;code&gt;tailwindStylesheet&lt;/code&gt; is required by the &lt;a href="https://github.com/tailwindlabs/prettier-plugin-tailwindcss#specifying-your-tailwind-stylesheet-path-tailwind-css-v4" rel="noopener noreferrer"&gt;Tailwind plugin's setup instructions&lt;/a&gt;. Point it to your actual CSS entry point containing the Tailwind import and your theme or custom utility definitions. The path is relative to &lt;code&gt;.prettierrc&lt;/code&gt;, not the file being formatted.&lt;/p&gt;

&lt;p&gt;Keep &lt;code&gt;prettier-plugin-tailwindcss&lt;/code&gt; last in the plugin array. If your project also uses Svelte, install its formatter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; prettier-plugin-svelte
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then replace the &lt;code&gt;plugins&lt;/code&gt; array with this one, keeping the other settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-astro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-svelte"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier-plugin-tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;.prettierignore&lt;/code&gt; for generated output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/
.astro/
.vercel/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prettier already ignores &lt;code&gt;node_modules&lt;/code&gt; by default. There is no general reason to exclude &lt;code&gt;vercel.json&lt;/code&gt;; it is a source configuration file that Prettier can format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatting on save in VS Code
&lt;/h2&gt;

&lt;p&gt;Merge these settings into &lt;code&gt;.vscode/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prettier.documentSelectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"**/*.astro"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"[astro]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Astro extension has its own formatter; these settings explicitly select the Prettier extension for &lt;code&gt;.astro&lt;/code&gt; files. The Prettier extension uses your project's locally installed Prettier. Open a trusted workspace and approve local module loading if prompted.&lt;/p&gt;

&lt;p&gt;For Svelte projects, also add &lt;code&gt;"**/*.svelte"&lt;/code&gt; to &lt;code&gt;prettier.documentSelectors&lt;/code&gt; and a &lt;code&gt;[svelte]&lt;/code&gt; setting with the same &lt;code&gt;editor.defaultFormatter&lt;/code&gt; value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking the setup locally and in CI
&lt;/h2&gt;

&lt;p&gt;Format the project, then check it without making changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prettier &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--write&lt;/span&gt;
npx prettier &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review the formatting diff before committing. &lt;code&gt;--check&lt;/code&gt; exits with a nonzero status if files need formatting, so it can fail a CI job. In CI, install the committed dependencies with &lt;code&gt;npm ci&lt;/code&gt; before running &lt;code&gt;npx prettier . --check&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If formatting fails, check that the stylesheet path exists, the Astro parser override is present, and the Tailwind plugin is last. If the CLI works but saving in VS Code does not, check the selected formatter and the Prettier output panel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The project now has an explicit plugin configuration, a Tailwind 4 stylesheet reference, and a formatting check you can use outside the editor. Keep the configuration and lockfile in Git so format-on-save and CI use the same rules.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://straffesites.com/en/blog/astro-setup-svelte-tailwindcss-vercel-prettier-typescript" rel="noopener noreferrer"&gt;full Astro setup guide&lt;/a&gt; covers the wider starter configuration, including Svelte, Vercel, and TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://straffesites.com/en/blog/integrate-prettier-astro-tailwindcss" rel="noopener noreferrer"&gt;straffesites.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>prettier</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>A guide to proper semantic markup for blog posts</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Thu, 03 Sep 2026 11:06:26 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/a-guide-to-proper-semantic-markup-for-blog-posts-lna</link>
      <guid>https://dev.to/seppegadeyne/a-guide-to-proper-semantic-markup-for-blog-posts-lna</guid>
      <description>&lt;p&gt;Semantic markup means choosing HTML elements for their meaning: one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; for your title, &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; for logical sections, &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; for images, &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; for your publication date, and JSON-LD BlogPosting data for search engines. This guide explains why that matters for SEO and gives you examples of each element that you can copy, paste, and validate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to semantic markup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html" rel="noopener noreferrer"&gt;Semantic markup&lt;/a&gt; uses HTML elements to make the structure and meaning of a page clear to browsers, search engines, and assistive technology. Give the blog post one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; for its title. Below it, use a logical hierarchy without skipping levels: &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; for main sections and &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; for subsections. This makes the article easier to scan and understand.&lt;/p&gt;

&lt;p&gt;You can also add an &lt;code&gt;id&lt;/code&gt; attribute to each &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, usually based on a short hyphenated version of the heading. A table of contents can then link directly to it with a fragment such as &lt;code&gt;#name-of-the-id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic structure of a blog post
&lt;/h2&gt;

&lt;p&gt;Here is an example of the basic structure of a blog post with semantic markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My website&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.svg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Company name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Main navigation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- aria-label instead of a heading: navigation doesn't belong in the content outline --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Main title&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Title 1&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 1&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Title 2&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 2&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Title 3&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 3&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Footer navigation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;copy;&lt;/span&gt; 2023 Company name&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the navigation does not need an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;. Headings describe content sections; an &lt;code&gt;aria-label&lt;/code&gt; names the &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; landmark instead. The heading hierarchy stays clean, while screen reader users can still distinguish one navigation area from another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Images and their alt text
&lt;/h2&gt;

&lt;p&gt;Images need the same care as the surrounding text. Use descriptive filenames and write alt text that explains the content or purpose of each informative image. Alt text is primarily an accessibility feature, though it can also give search engines useful context.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; provides a visible caption that connects the image to your article. The alt text describes the image for someone who cannot see it; the caption is visible to everyone. The two may overlap, but they do not need to repeat each other word for word.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"example-image.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"An example of a well-formatted image"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;figcaption&amp;gt;&lt;/span&gt;An example of a well-formatted image&lt;span class="nt"&gt;&amp;lt;/figcaption&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; for a machine-readable publication or modification date. The &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt; element is suitable for the article author's contact information, not for every postal address that happens to appear in the copy. Link to a useful author page if you have one.&lt;/p&gt;

&lt;p&gt;Here is a simple example using &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;time&lt;/span&gt; &lt;span class="na"&gt;datetime=&lt;/span&gt;&lt;span class="s"&gt;"2023-03-21"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;March 21, 2023&lt;span class="nt"&gt;&amp;lt;/time&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;address&amp;gt;&lt;/span&gt;
  Written by &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"author-page.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Author&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  Follow me on &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://twitter.com/theauthor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Twitter&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/address&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Schema markup for blog posts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data" rel="noopener noreferrer"&gt;Schema markup&lt;/a&gt; gives search engines an explicit description of the page. A blog post can use &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/article" rel="noopener noreferrer"&gt;Article&lt;/a&gt; or its more specific &lt;code&gt;BlogPosting&lt;/code&gt; type. If the page contains a genuine FAQ, &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/faqpage" rel="noopener noreferrer"&gt;FAQPage&lt;/a&gt; can describe those questions and answers too.&lt;/p&gt;

&lt;p&gt;Here is a &lt;code&gt;BlogPosting&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BlogPosting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A guide to the right semantic markup for blog posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/blog/semantic-markup-blog-posts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/image/1x1/image.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/image/4x3/image.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/image/16x9/image.jpg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"datePublished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-03-20T12:42:21.345Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dateModified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-03-21T12:12:44.220Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/the-author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://twitter.com/the-author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://www.linkedin.com/in/the-author/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publisher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Company name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://www.linkedin.com/company/company-name/"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"logo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ImageObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/logo.svg"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is an &lt;code&gt;FAQPage&lt;/code&gt; example using &lt;code&gt;Question&lt;/code&gt; and &lt;code&gt;Answer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FAQPage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mainEntity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Question"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Why is semantic markup important for SEO?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"acceptedAnswer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Answer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Semantic markup helps search engines understand the structure and meaning of a page and gives assistive technologies useful relationships. It can support indexing, but it does not guarantee rankings or traffic."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Question"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Should I always use alt text for images?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"acceptedAnswer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Answer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Use descriptive alt text for informative images. Give purely decorative images an empty alt attribute so screen readers can skip them. Alt text primarily supports accessibility and can also provide search engines with useful context."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always validate pasted markup. Google's &lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;Rich Results Test&lt;/a&gt; shows whether Google recognizes supported structured data, while the &lt;a href="https://validator.schema.org/" rel="noopener noreferrer"&gt;Schema.org validator&lt;/a&gt; checks the underlying vocabulary. URL inspection in Google Search Console shows how Google sees the published page. As a quick local check, the JSON must be accepted by &lt;code&gt;JSON.parse&lt;/code&gt; without HTML-entity corruption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Correct semantic markup gives readers, assistive technology, and search engines a clearer article. Use headings in order, describe informative images with useful alt text, and add valid schema markup where it accurately reflects the page. For the editorial side, I also wrote a guide on &lt;a href="https://straffesites.com/en/blog/blog-post-structure-tips" rel="noopener noreferrer"&gt;formatting and structuring a blog post&lt;/a&gt;. MDN has a useful reference on &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html" rel="noopener noreferrer"&gt;semantics in HTML&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published on &lt;a href="https://straffesites.com/en/blog/a-guide-to-semantics-for-blog-posts" rel="noopener noreferrer"&gt;straffesites.com&lt;/a&gt; — I build fast, semantic websites there.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>seo</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Supercharge your Shopify pages with Liquid shortcodes for collections</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Fri, 02 Jun 2023 11:33:14 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/supercharge-your-shopify-pages-with-liquid-shortcodes-for-collections-32l3</link>
      <guid>https://dev.to/seppegadeyne/supercharge-your-shopify-pages-with-liquid-shortcodes-for-collections-32l3</guid>
      <description>&lt;p&gt;I will share a handy trick I recently applied to a client's website selling &lt;a href="https://rugexpertiseshop.nl/pages/steunzolen-bekkenpijn" rel="noopener noreferrer"&gt;orthopedic insoles&lt;/a&gt;. We needed a way to showcase collections in a page's text. Unlike WordPress, this isn't a feature directly offered by Shopify. We can achieve this with some Liquid, Shopify's template language. Look at the link above for an example of this implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making your Shopify theme shortcode-ready
&lt;/h2&gt;

&lt;p&gt;The first step in our journey involves tweaking your theme's &lt;code&gt;main-page.liquid&lt;/code&gt; file, located under the &lt;code&gt;/sections&lt;/code&gt; directory. We'll make a small but impactful change here: replace &lt;code&gt;{{ page.content }}&lt;/code&gt; with &lt;code&gt;{% render 'shortcode', page: page.content %}&lt;/code&gt;. This modification tells Shopify to load the snippet named &lt;code&gt;shortcode.liquid&lt;/code&gt; and pass it the variable named &lt;code&gt;page&lt;/code&gt; containing &lt;code&gt;page.content&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the liquid shortcodes
&lt;/h2&gt;

&lt;p&gt;Once we've prepped our theme, it's time to create two new files within the &lt;code&gt;/snippets&lt;/code&gt; folder: &lt;code&gt;shortcode.liquid&lt;/code&gt; and &lt;code&gt;shortcode-collection.liquid&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;shortcode.liquid&lt;/code&gt;, we'll be inserting the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;liquid&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;empty&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nt"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'[collection='&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nt"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content_parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;']'&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nt"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;shortcode_handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content_parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

           &lt;/span&gt;&lt;span class="nt"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

           &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;shortcode_handle&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;empty&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nt"&gt;render&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'shortcode-collection'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;shortcode_handle&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nt"&gt;else&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nt"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;p&amp;gt;No collection found with the handle "'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;shortcode_handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'".&amp;lt;/p&amp;gt;'&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt;

           &lt;/span&gt;&lt;span class="nt"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;content_parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nt"&gt;else&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nt"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code checks if a shortcode in the format &lt;code&gt;[collection=name-collection]&lt;/code&gt; is present within the text. If detected, the content will be split into two parts, and &lt;code&gt;shortcode-collection.liquid&lt;/code&gt; will be loaded. If no shortcode is found, &lt;code&gt;page.content&lt;/code&gt; is loaded as is. &lt;/p&gt;

&lt;p&gt;Now, we'll add the following code to &lt;code&gt;shortcode-collection.liquid&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
   &amp;lt;article&amp;gt;
       &amp;lt;h2&amp;gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&amp;lt;/h2&amp;gt;
       &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
           &amp;lt;article&amp;gt;
               &amp;lt;a href='&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;'&amp;gt;
                   &amp;lt;img
                       src='&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;featured_image&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;image_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'600'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'600'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;'
                       alt='&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;'
                       width='600'
                       height='600'
                       loading='lazy'
                   &amp;gt;
               &amp;lt;/a&amp;gt;

               &amp;lt;a href='&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;'&amp;gt;
                   &amp;lt;h3&amp;gt;
                       &lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;
                   &amp;lt;/h3&amp;gt;
               &amp;lt;/a&amp;gt;

               &amp;lt;p&amp;gt;
                   &lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;money&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;
               &amp;lt;/p&amp;gt;
           &amp;lt;/article&amp;gt;
       &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endfor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
   &amp;lt;/article&amp;gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
   &amp;lt;p&amp;gt;No collection found with the handle "&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;shortcode_handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;".&amp;lt;/p&amp;gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is responsible for rendering the products of a given collection. Remember, you'll likely need to style the output with CSS to match your website's looks. I intentionally used the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element, along with heading elements &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, to leverage semantic markup, which can help your site rank higher on Google. For more information on &lt;a href="https://dev.to/seppegadeyne/unlocking-the-power-of-semantics-in-html-4e9j"&gt;semantic markup&lt;/a&gt; and improving your Google ranking, check out my other articles at &lt;a href="https://straffesites.com/en/blog" rel="noopener noreferrer"&gt;Straffe Sites&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With some creativity and Liquid code, we've created a system that allows for the flexible insertion of Shopify collections into any part of your webpage.&lt;/p&gt;

&lt;p&gt;This technique can be a real game-changer for those who want to provide a more dynamic and customized shopping experience. It's another example of the flexibility and power that Shopify's Liquid language offers.&lt;/p&gt;

&lt;p&gt;But remember, with great power comes great responsibility. Always double-check your code and test your pages thoroughly to ensure everything works as expected. And remember to style your output with CSS to maintain a consistent and appealing visual aesthetic across your site.&lt;/p&gt;

&lt;p&gt;I hope this tutorial has been helpful and has given you ideas for your Shopify projects. Remember, the possibilities are nearly endless when customizing your e-commerce store. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>shopify</category>
      <category>liquid</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Unlocking your website's potential: eliminate render-blocking resources</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Mon, 08 May 2023 09:35:42 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/unlocking-your-websites-potential-eliminate-render-blocking-resources-26i2</link>
      <guid>https://dev.to/seppegadeyne/unlocking-your-websites-potential-eliminate-render-blocking-resources-26i2</guid>
      <description>&lt;p&gt;Do you need help constantly seeing poor Lighthouse ratings from &lt;a href="https://pagespeed.web.dev" rel="noopener noreferrer"&gt;Google PageSpeed Insights&lt;/a&gt;? The main issue is often render-blocking resources. In this blog post, I'll walk you through some straightforward steps to eliminate these performance issues and help your website achieve the speed boost it deserves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimize JavaScript loading to prevent page load delays
&lt;/h2&gt;

&lt;p&gt;A simple tweak can impact your website's performance. Optimizing loading ensures no longer render-blocking the initial rendering of your page. &lt;a href="https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources/?utm_source=lighthouse&amp;amp;utm_medium=lr" rel="noopener noreferrer"&gt;Eliminating render-blocking&lt;/a&gt; is facilitated through the use of a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" rel="noopener noreferrer"&gt;Promise&lt;/a&gt;, which allows scripts to be loaded asynchronously without blocking the rendering of the page, ensuring that they are injected into the page only after the initial HTML document has been fully loaded and parsed. Some scripts, like chat widgets, are introduced toward the end of the page or when the user interacts with the website.&lt;/p&gt;

&lt;p&gt;Here's an example of how to optimally load Google Tag Manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Function to load JavaScript to the DOM&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadJS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Load Google Tag Manager &lt;/span&gt;
    &lt;span class="nf"&gt;loadJS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXX`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gtm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gtm.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gtm.start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gtm.uniqueEventId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageLoad&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following example demonstrates how to load a chat widget only when the user begins scrolling on the website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Function to load JavaScript to the DOM&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadJS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
            &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleScroll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Load the external JavaScript&lt;/span&gt;
      &lt;span class="nf"&gt;loadJS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://static.chatbotkit.com/integrations/widget/v2.js`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatbotkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;// Remove the event listener after executing the code&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleScroll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleScroll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Embedding videos without hindering page load
&lt;/h2&gt;

&lt;p&gt;Adding multimedia, like videos, can provide a rich experience for your users. However, loading external resources such as videos can significantly slow page load time. A solution to this is to initially display a thumbnail of the video and only load the video when the user expresses interest by clicking on the thumbnail.&lt;/p&gt;

&lt;p&gt;I applied this technique for a client on their page: &lt;a href="https://www.verhuurwinkel.nl/silent-disco-huren" rel="noopener noreferrer"&gt;Hire silent disco at Verhuurwinkel.nl&lt;/a&gt;. It worked seamlessly, ensuring the page loaded faster and providing interactive video content.&lt;/p&gt;

&lt;p&gt;Here’s how you can implement this technique for a YouTube video:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-youtube-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-thumbnail-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/images/thumbnail.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ALT text for your image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1200&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;675&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cursor: pointer;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Function to handle thumbnail click event&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleThumbnailClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iframe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YouTube video player&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.youtube.com/embed/X4z0ojfdLac&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1200&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;675&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;frameborder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allowfullscreen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allowfullscreen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-youtube-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-thumbnail-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Replace the image with the iframe&lt;/span&gt;
        &lt;span class="nx"&gt;contentDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;contentDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Wait for DOM to be ready&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-thumbnail-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleThumbnailClick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, an image thumbnail of the video is initially displayed on the webpage. When the user clicks on the thumbnail, a  &lt;code&gt;handleThumbnailClick&lt;/code&gt; function is triggered, which replaces the thumbnail with the actual YouTube video iframe. This way, the external video resource is only loaded when it's needed, which helps in reducing the initial load time of your webpage.&lt;/p&gt;

&lt;p&gt;By following the above method, you can embed videos in your website without negatively impacting the page load time, further unlocking your website's potential for speed and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Following the steps outlined in this blog post, you can &lt;a href="https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources/?utm_source=lighthouse&amp;amp;utm_medium=lr" rel="noopener noreferrer"&gt;eliminate render-blocking resources&lt;/a&gt; from your website and enhance its overall &lt;a href="https://straffesites.com/en/blog/website-performance" rel="noopener noreferrer"&gt;website performance&lt;/a&gt;. Try these tips, and watch your website's loading time dramatically improve!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>html</category>
      <category>performance</category>
    </item>
    <item>
      <title>Crafting a mobile menu with Tailwind CSS without JavaScript</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Fri, 28 Apr 2023 08:34:10 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/crafting-a-mobile-menu-with-tailwind-css-without-javascript-1814</link>
      <guid>https://dev.to/seppegadeyne/crafting-a-mobile-menu-with-tailwind-css-without-javascript-1814</guid>
      <description>&lt;p&gt;Welcome to this blog post, where I'll walk you through building a mobile menu using only &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; and HTML, without JavaScript. This approach is excellent for enhancing website performance, as minimizing the use of JavaScript can help your site load faster. You can check out a &lt;a href="https://straffesites.com/en" rel="noopener noreferrer"&gt;live example&lt;/a&gt; of this technique on my website. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;peer-*&lt;/code&gt; from Tailwind CSS for animations and state
&lt;/h2&gt;

&lt;p&gt;To create the animations for our mobile menu, we'll utilize the &lt;a href="https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-sibling-state" rel="noopener noreferrer"&gt;&lt;code&gt;peer-*&lt;/code&gt; utility from Tailwind CSS&lt;/a&gt;. This allows us to control the state of a sibling element, like an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element of the type &lt;code&gt;checkbox&lt;/code&gt;. By placing all HTML elements within the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element, we can make them dependent on the state of the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element. We will then hide the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element and make the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element respond to touch or cursor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative z-40 cursor-pointer px-3 py-6"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"peer hidden"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the hamburger icon with &lt;code&gt;before:&lt;/code&gt; and &lt;code&gt;after:&lt;/code&gt; pseudo-elements
&lt;/h2&gt;

&lt;p&gt;To craft the hamburger icon, we'll use the &lt;a href="https://tailwindcss.com/docs/hover-focus-and-other-states#before-and-after" rel="noopener noreferrer"&gt;&lt;code&gt;before:&lt;/code&gt; and &lt;code&gt;after:&lt;/code&gt; pseudo-elements&lt;/a&gt;. We'll start with a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element with a height of &lt;code&gt;1px&lt;/code&gt; and a width equal to the &lt;code&gt;w-7&lt;/code&gt; value. In this example, the middle line is set to &lt;code&gt;transparent&lt;/code&gt;, so we only see the lines from &lt;code&gt;before:&lt;/code&gt; and &lt;code&gt;after:&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative z-40 cursor-pointer px-3 py-6"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"peer hidden"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative z-50 block h-[1px] w-7 bg-black bg-transparent content-[''] before:absolute before:top-[-0.35rem] before:z-50 before:block before:h-full before:w-full before:bg-black before:transition-all before:duration-200 before:ease-out before:content-[''] after:absolute after:right-0 after:bottom-[-0.35rem] after:block after:h-full after:w-full after:bg-black after:transition-all after:duration-200 after:ease-out after:content-[''] peer-checked:bg-transparent before:peer-checked:top-0 before:peer-checked:w-full before:peer-checked:rotate-45 before:peer-checked:transform after:peer-checked:bottom-0 after:peer-checked:w-full after:peer-checked:-rotate-45 after:peer-checked:transform"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Completing the mobile menu with additional elements
&lt;/h2&gt;

&lt;p&gt;Now, let's add more elements to complete the mobile menu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A full-screen background with a &lt;a href="https://tailwindcss.com/docs/backdrop-blur" rel="noopener noreferrer"&gt;backdrop blur&lt;/a&gt; filter&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element for the menu items with an &lt;a href="https://tailwindcss.com/docs/animation" rel="noopener noreferrer"&gt;animation&lt;/a&gt;, which scrolls the menu from right to left&lt;/li&gt;
&lt;li&gt;The menu itself, using a &lt;code&gt;&amp;lt;menu&amp;gt;&lt;/code&gt; element (which functions like a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; element, but is better for &lt;a href="https://dev.to/seppegadeyne/unlocking-the-power-of-semantics-in-html-4e9j"&gt;semantics in HTML&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative z-40 cursor-pointer px-3 py-6"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"peer hidden"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative z-50 block h-[1px] w-7 bg-black bg-transparent content-[''] before:absolute before:top-[-0.35rem] before:z-50 before:block before:h-full before:w-full before:bg-black before:transition-all before:duration-200 before:ease-out before:content-[''] after:absolute after:right-0 after:bottom-[-0.35rem] after:block after:h-full after:w-full after:bg-black after:transition-all after:duration-200 after:ease-out after:content-[''] peer-checked:bg-transparent before:peer-checked:top-0 before:peer-checked:w-full before:peer-checked:rotate-45 before:peer-checked:transform after:peer-checked:bottom-0 after:peer-checked:w-full after:peer-checked:-rotate-45 after:peer-checked:transform"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fixed inset-0 z-40 hidden h-full w-full bg-black/50 backdrop-blur-sm peer-checked:block"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="ni"&gt;&amp;amp;nbsp;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fixed top-0 right-0 z-40 h-full w-full translate-x-full overflow-y-auto overscroll-y-none transition duration-500 peer-checked:translate-x-0"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"float-right min-h-full w-[85%] bg-white px-6 pt-12 shadow-2xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog post, we've successfully built a lightweight mobile menu using &lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; and HTML without JavaScript. This approach is crucial for optimizing your website's load speed and &lt;a href="https://straffesites.com/en/blog/how-to-rank-higher-on-google" rel="noopener noreferrer"&gt;ranking higher in search engines&lt;/a&gt;. So try and experience the benefits of a more performant, JavaScript-free mobile menu.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>html</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Unlocking the power of semantics in HTML</title>
      <dc:creator>Seppe Gadeyne</dc:creator>
      <pubDate>Thu, 27 Apr 2023 11:57:37 +0000</pubDate>
      <link>https://dev.to/seppegadeyne/unlocking-the-power-of-semantics-in-html-4e9j</link>
      <guid>https://dev.to/seppegadeyne/unlocking-the-power-of-semantics-in-html-4e9j</guid>
      <description>&lt;p&gt;Welcome to the world of semantics, where code speaks the language of content. In today's fast-paced digital landscape, creating accessible and search engine-friendly web pages is crucial for success. However, as a &lt;a href="https://straffesites.com/en/freelance-web-developer" rel="noopener noreferrer"&gt;freelance web developer&lt;/a&gt;, I've noticed that many newly built websites need improvement regarding semantics in HTML. In this blog post, we'll dive into the importance of semantics, explore a basic HTML structure with the correct semantics, and provide resources for further learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The importance of semantics
&lt;/h2&gt;

&lt;p&gt;Using semantics correctly allows you to communicate the meaning of content blocks on your website through code. Semantics are of great value for search engines and screen readers, making your site more accessible and easily understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  A basic HTML structure with proper semantics
&lt;/h2&gt;

&lt;p&gt;Here's an example of how to structure a page with the correct semantics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Page&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;This is my page&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.svg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"My brand"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Primary navigation&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Article Title&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Subtitle 1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 1&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Subtitle 2&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 2&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Subtitle 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Paragraph 3&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Footer navigation&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;copy;&lt;/span&gt; 2023 My Brand&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might notice that the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element is positioned immediately after the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element. This implies that subsequent heading elements should begin with the &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; element, and beneath the &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; element, there should be &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; elements. Sticking to these rules is essential for implementing semantics correctly in HTML. For more guidance, refer to resources on &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html" rel="noopener noreferrer"&gt;semantics in HTML&lt;/a&gt; from MDN.&lt;/p&gt;

&lt;p&gt;Placing the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element right below the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element can be challenging visually organizing your layout. Therefore, I usually make this &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element visible only to screen readers using CSS. Remember that this element's content is crucial for search engines, so ensure it's optimized for SEO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources and tools for better semantics
&lt;/h2&gt;

&lt;p&gt;Many sectioning elements in HTML need to be identified by a heading element as a child. You can consult the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element" rel="noopener noreferrer"&gt;HTML elements reference&lt;/a&gt; from MDN for each element's requirements, and you can use a tool like &lt;a href="https://gsnedders.html5.org/outliner/" rel="noopener noreferrer"&gt;HTML5 Outliner&lt;/a&gt; to check your work. If you've missed a heading element, this tool will make finding and correcting the issue easy. By implementing the correct markup, you'll create a well-structured table of contents for your page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantics for blog posts
&lt;/h2&gt;

&lt;p&gt;For those interested in diving deeper into the topic, I've written a separate blog post about the specific elements and &lt;a href="https://straffesites.com/en/blog/a-guide-to-semantics-for-blog-posts" rel="noopener noreferrer"&gt;semantics to use for blog post pages&lt;/a&gt;. Check it out to enhance your understanding and application of HTML semantics in blogging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Understanding and applying the correct semantics in HTML is essential for creating accessible, search engine-friendly websites. By following the basic structure provided and using the resources mentioned, you'll be on your way to unlocking the full potential of semantics in your web development projects. Remember, code is not only about functionality – it's also about communication. So make your code speak the language of your content with the power of semantics.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>google</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
