Skip to content

<style scoped> in Vue SFCs is not processed, causing CSS leakage between components #102

@JovanVeljanoski

Description

@JovanVeljanoski

I've noticed that when using Vue single-file components (.vue files) with ipyvue, the <style scoped> attribute appears to be ignored. CSS rules defined in one component can unintentionally affect other components, which makes styling complex applications challenging.

Expected Behavior

In standard Vue tooling (Vue CLI, Vite), <style scoped> transforms CSS selectors to include a unique data attribute, ensuring styles only apply to elements within that component:

/* Input */
.card-container { background: red; }

/* Output after Vue's PostCSS processing */
.card-container[data-v-f3f3eg9] { background: red; }

Actual Behavior

In ipyvue, the scoped attribute is parsed but not processed. CSS is injected into as-is, making all styles effectively global.

Reproduction Example

Component A (component_a.vue):

<template>
  <div class="container">Component A</div>
</template>

<style scoped>
.container { background-color: red; }
</style>

Component B (component_b.vue):

<template>
  <div class="container">Component B</div>
</template>

<style scoped>
.container { background-color: blue; }
</style>

Result: Both components end up with the same background color (whichever CSS loads last wins), even though both use <style scoped>.

Investigation

I looked into the ipyvue source and found:

  1. In VueTemplateRenderer.js, styles are extracted and injected into document.head, but the scoped attribute doesn't trigger any CSS transformation:
const css = model.get('css') || (vuefile.STYLE && vuefile.STYLE.content);
const cssId = (vuefile.STYLE && vuefile.STYLE.id);

if (css) {
  if (cssId) {
    // Uses ID for deduplication, but no scoping transformation
    const prefixedCssId = `ipyvue-${cssId}`;
    // ...
  }
}
  1. Interestingly, httpVueLoader.js contains a scopeStyles function that modifies CSS selectors — this suggests there's partial infrastructure for scoping that could potentially be extended

Workaround

Currently, I'm manually prefixing all CSS class names with the component name (e.g., .sidepanel-card-container instead of .container), but this is error-prone and defeats the purpose of having scoped styles.

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