-
Notifications
You must be signed in to change notification settings - Fork 915
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
Scoped CSS Doesn't work on dynamic content #559
Comments
Thank you for your filling! Can you provide the minimum reproduction code please? |
I created a repo showing this issue. https://github.com/ramakrishnamundru/Vue-loader-scoped just remove scoped for the plugin css and see changes |
Thank you for your codes! scoped CSS with vue-loader & vue core can not give scopeId to the dynamic content with jQuery etc. src/components/Hello.vue mounted: function() {
$('#switch').lc_switch('ON', 'OFF', this.$options._scopeId);
} src/assets/LC-switch/lc_switch.js$.fn.lc_switch = function(on_text, off_text, scopeId) {
// ...
// should be changed dynamic content with scopeId
// e.g. cod_on_text & ckd_off_txt
var on_label = (ckd_on_txt) ? '<div ' + scopeId + ' class="lcs_label lcs_label_on">'+ ckd_on_txt +'</div>' : '';
var off_label = (ckd_off_txt) ? '<div ' + scopeId + ' class="lcs_label lcs_label_off">'+ ckd_off_txt +'</div>' : '';
// ... |
Maybe, But in this way I have to edit most of the plugin files as many will create dynamic content because lc_switch is just an example. Is in't there a way to add scopeId to the root of the component and modify the css as the children of the root scopeId. Like:
|
Something like this might work (untested): Vue.directive('scope', {
bind: updateScopeId,
componentUpdated: updateScopeId
}
function updateScopeId(el, __, vNode) {
const vm = vNode.context
const scopeId = vm & vm.$options._scopeId
if (scopeId) {
vm.$nextTick(() => { // wait till DOM was updated
setScopeRecursively(el, `v-${scopeId}`)
})
}
}
function setScopeRecursively(el, scopeString) {
const nodes = el.children
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i]
if (node.dataset[scopeString] !== '') {
node.dataset[scopeString] = ''
}
if (node.children.length > 0) {
setScopeRecursively(node, scopeString)
}
}
} Usage <div v-scope>
<!--
if you add any elements in here with jQuery,
the directive will add the scope data attributes for you.
it will also re-check whenever the component updated, in case Vue changed the DOM
-->
</div> Limitations
|
@LinusBorg your code didn't work for me. the setScopeRecursively function is never executed. But I think the way of adding scopeId to the root element and modifying CSS accordingly is better solution. Is there a way you can implement this in vue loader.... |
If you want to use a base base class on the root element and nested styled under it, you don't need scope, just use a unique classname. |
@kazupon , @LinusBorg I there a way you can make vue-loader add and remove the style tag for scoped css along with the component i.e style tag added to dom when component created and removed when component destroyed, |
@yyx990803 This is clearly a problem because any thing dynamic should have it's css applied globally. So, It will effect content of other components. So the solution I think of is to move the style tag with scoped attribute into the template, so that it will only appear when its needed. otherwise many jquery plugins css will have to be applied globally, which have a lot of problems. |
That CSS is still being applied globally - it would merely reduce the "risk's" probability a little, and at worst create a false sense of security because it works as long as two components with matching CSS are not in the document together at the same - until they are, because your changed something in your app - and now you wonder why CSS is screwed up. So I still don't see how we could have truly scoped CSS applied by vue-loader for elements that it doesn't know of, because third party libs create them during runtime. |
If the style tag is removed from the dom then its content is also removed. and no styles will be applied to other components. about style tags. I think it is possible to accommodate dynamic elements css by adding the style tag to template like this:
just bundling all the files with scoped attribute and adding them to template will ensure that the css only comes when required and is removed with the component when switching route. |
Of course, I don't deny that. But that CSS is still not scoped to the component, it's still applied to the whole document. So if you have two component with conflicting CSS rules in the document at the same time, the CSS will be screwed up even with this method. So as I said above, it's a small improvement, but the "securtity" that it seems to bring is very brittle. The ´discussion you linked to doesn't revolve around scoping issues either, AFAICT, |
OK, Now I understand your concern, and the clear meaning of scope. Then is there any way you can add another mode like "bound" or something else which shows the css loaded is applied globally, but can also be moved with the template hence separating the confusion between the "security" the scoped css provides , and the "flexibility" the bound to the component css provides. Because it is not just about third party libraries, but many people create dynamic content and the loss of styling to the content is a clear drawback to the loader. |
Please open a new issue as a featue request with a detailed description of what you want, and why it's useful. This issue was about scoped CSS, we should start clean. However, as a disclaimer: I don't think that his will have a high priority, because (aside from the fact that it's a very common practice to serve all CSS as one bundle initially) the focus of vue-loader files it to take care of CSS for Vue components, and those can be scoped, so there's no issue. Its focus is not to support any kind of dynamic styling for any a third-party lib that might come with its own CSS in the component by some third party lib.
I don't understand what kind of content you refer to here. |
I mean content like dynamic chat or task manager, editable tables etc.. And thanks I will file a new issue. |
Well, either those are created with Vue, so you can use scoped CSS (so you have no problem), or they are created with third-party libs - like jQuery plugins. I don't see a third possibility that woudl make sense. |
I had the same problem,and just give up using |
@aboutqx you can use the deep selector as @yyx990803 mentioned here |
I have some component that are filled with content from the backend as HTML and will be rendered with |
Vue bills itself as something you can transition into. Not having the scoped css apply to dynamic elements breaks that promise. e.g. when I dynamically add elements with d3. Yes, I can eventually transition to d3 + vue templates, but this means a lot more up front work when Vue should just work out of the box. |
I tried something similar to @LinusBorg's Below is my version:
|
I am using D3.js inside of Vue.js single file components. I was trying to style some elements that were added to the DOM after the Vue component was created and found that deep selectors work well for this. I wanted to share what I found in the hope that it helps someone. To apply deep selectors, you start by selecting an element that exists in your For example, if I want to change the colors of the axes (path) and tick marks (line) in a line chart to blue, then I would use this deep selector:
Notice that I did not select any other child elements that were between the This also means that you need to be careful when nesting styles. Make sure that you use the deep selectors properly and that you do not mix up any nested styles with deep selector styles. If you do mix them up, then your deep selector styles probably won’t work. It is important to note that the If you don’t see your deep selector changes in the browser, then refresh it |
If it helps anyone, you can have multiple <style>'s in a single file template. For example... MyTemplate.vue
|
When using scoped CSS the styles and the elements are given data- attributes. But when content is added Dynamically it won't have those data- attributes. So the styles are not applying to the dynamic content.
I think it's better to add a data- attribute to the root element of the template and add the styles as the children of that attribute instead of adding attributes to individual elements..
The text was updated successfully, but these errors were encountered: