Skip to content

A global <style> before a <style scoped> silently drops the scoped CSS #423

Description

@tylerturdenpants

Summary

When a template contains a plain <style> element before a <style scoped> one, the scoped block's CSS is silently discarded: no stylesheet is emitted for it, no classes are collected from it, and no error or warning is produced.

Cause

src/build/template-plugin.js:119 selects the style element to extract by tag alone, ignoring attributes:

let styleTag = node.body.find(
  (n) => n.type === 'ElementNode' && n.tag === 'style',
);

if (hasScopedAttribute(styleTag)) {

With a global <style> first, find returns that one, hasScopedAttribute is false, and the whole extraction branch is skipped -- so addInfo and request.inline.create never run for the scoped block. The ElementNode visitor then still matches the scoped element later in the traversal and returns null for it, removing it from the compiled template.

Net effect: the scoped CSS is deleted from the output and never emitted anywhere.

Reproduction

<template>
  <style>
    .global { color: red; }
  </style>

  <style scoped>
    .scoped { color: blue; }
  </style>
</template>

.scoped is dropped. Reversing the order of the two blocks makes it work.

The same applies to a second <style scoped> in one template: only the first style element is ever considered.

Suggested fix

Find the first scoped style element rather than the first style element:

let styleTag = node.body.find(
  (n) => n.type === 'ElementNode' && n.tag === 'style' && hasScopedAttribute(n),
);

That leaves the existing "only at the root" and nested-block errors intact. If supporting more than one <style scoped> per template is out of scope, an explicit error for the second one would at least be louder than dropping it.

How this surfaced

Found while reviewing #422, which adds a stylelint customSyntax for inline blocks. That syntax lints every root-level <style scoped>, so it reports problems in CSS the build silently discards. Rather than teach the linter to replicate this behaviour, #422 documents the divergence and points here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions