Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using scoped CSS, element in slot within transition element doesn't apply child scope #820

Open
RuneInBoots opened this issue May 18, 2017 · 10 comments

Comments

@RuneInBoots
Copy link

Version

11.0.0

Reproduction link

https://github.com/RuneInBoots/vue-issue

Steps to reproduce

We tried to use scoped CSS in our components.
In our application we also make use of slots.

We came across the problem that the elements in the slots were only following the parent scope.
We know this because we inspected the element and saw only one data-v-[id], and because our styles weren't applied =]

After searching we found out that our issue lied with the <transition> around our child component.

// childComponent.vue

<template lang="html">
  <!-- <transition> -->
    <section>
      <h1>Child component</h1>
      <h2>text inside child</h2>
      <p>child sets background to gold</p>
      <h2>text from parent with slot</h2>
      <slot name="foobar"></slot>
    </section>
  <!-- </transition> -->
</template>

<style lang="css" scoped>
  p {background-color: gold;}
</style>

// parentComponent.vue

<template lang="html">
  <section>
    <h1>parent component</h1>
    <h2>text inside parent</h2>
    <p>parent sets color to crimson</p>
    <child-component>
      <p slot="foobar"> text from inside parent trough slot</p>
    </child-component>
   </section>
  </section>
</template>

<script>
  import childComponent from 'components/childComponent.vue';

  export default {
    components: {childComponent}
  }
</script>

<style lang="css" scoped>
  p {color: crimson;}
</style>

What is expected?

the text "text from inside parent trough slot" should have the color crimson and background-color gold. It should follow both the parent and the child scope.

What is actually happening?

the text only get the color crimson. it doesn't follow the CSS of the child scope.

@RuneInBoots
Copy link
Author

screen shot 2017-05-18 at 21 14 44

screen shot 2017-05-18 at 21 14 56

@Alexandre-Georges
Copy link

I have a similar issue

@pezillionaire
Copy link

@RuneInBoots is absolutely correct that this is how slotted content should behave with scoped CSS. I've also run into this with scoped components and breaks the fundamental way CSS is supposed to work.

The "Cascading" aspect of Cascading Style Sheets dictates that styling should apply to the child of the parent element. When data/elements are slotted into the component that data/elements then become a child of the component itself. Having scoped styling should still respect the "law" of CSS in this regard.

Seemingly, the way around this now seems to be unscoped styles in the component. This then breaks with the idea of componentization. I want the styling in my component to ONLY apply to that component, otherwise I might as well just use global stylesheets (one of the things that the concept of components is supposed to "solve")

All this said, I think this is a pretty big issue and would like to see it resolved.

@senritsu
Copy link

senritsu commented Sep 21, 2017

I might have a related issue, although i am not quite sure and can't reliably reproduce it.

In my case when i have a situation like

<template lang="html">
  <wrapper-component>
    <!-- ... -->
    <div v-if="bar" slot="header" class="foo">
      <span class="bar">{{ bar }}</span>
    </div>
    <!-- ... -->
  </wrapper-component>
</template>

And assuming scope data attributes called data-1 for the wrapper-component and data-2 for the component in question:

With scoped styling for .foo, if bar is false at initial component render, .foo does not get the correct scope attribute added when it enters the DOM later, it only gets data-1.

With an added template tag as a workaround like this:

<template lang="html">
  <wrapper-component>
    <!-- ... -->
    <div slot="header" class="foo">
      <template v-if="bar">
        <span class="bar">{{ bar }}</span>
      </template>
    </div>
    <!-- ... -->
  </wrapper-component>
</template>

It works just fine since .foo is in the DOM from the beginning and correctly has data-1 data-2.

Unfortunately i can't seem to reproduce it properly.

  • In synthetic tests on webpackbin .foo and all of its children only ever have data-2.
  • In synthetic tests in our application .foo and all of its children all have data-1 data-2.
  • As mentioned before, in the practical case where the issue arises, .foo has data-1 while all of its children have data-1 data-2. If the v-if condition is true from the start, .foo also has data-1 data-2.

@DaxChen
Copy link

DaxChen commented Sep 29, 2017

+1 for similar structure of @senritsu's example.
I'm using v-if on default slot.
Currently using the template workaround and work, thanks @senritsu!

vue-loader version: 12.2.2
vue version: 2.4.4

@mobilehobo
Copy link

Just ran into this issue myself. Currently using the /deep/ scss selector to get around it. If there's a better way to go about this, I'm all ears. :D

@tessaSAC
Copy link

hehehe yw @mobilehobo

@StaverDmitry
Copy link

StaverDmitry commented Jul 10, 2019

Hi guys, I'm from the future 😄 and I have the same issue, but in my case the v-if is on the slot itself within the wrapper-component.
Weird thing is that it was working fine for quite some time until now and I haven't even touched a thing related to it (I confirmed it additionally), it just happened after some merges.
Another weird thing is that it only happens on initial render, if I go and just re-save the wrapper component to trigger hot-reload, the scope attribute of the parent component is set correctly ¯_(ツ)_/¯
The only way I found to make it work is with use of /deep/ but it doesn't feel right.

@Karodar
Copy link

Karodar commented Jul 28, 2021

Guys, we're using $vm0.$options._scopeId in context this, for overwrite selectors weight in child slot scope.

image
image
image

Before:

image

After:

image

@lopis
Copy link

lopis commented Jul 24, 2023

I believe I've hit this same issue today. The scoped styles in the parent's slot stopped working when I removed an unrelated component from the child template. I can't make sense out of it. I did have a v-if in the child's slot. I moved that v-if to a new wrapper div around the child's slot, and it seems to work. This behaviour was very unexpected.

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

No branches or pull requests