2.0.0-rc.7
http://codepen.io/codysherman/pen/qaArqJ?editors=1010
Have an element already have an !important display trait, such as one of Bootstrap's 'visible-*' classes.
Vue should hide the element based on the v-show.
Because v-show doesn't have an !important tag, it is overruled. In my opinion, in the event of a conflict, the tie should obviously go to Vue, as it is getting its logic dynamically. Angular's ng-show applies the !important tag for this reason.
Please no. The _!important_ level is already used in some components to purposely override Vue v-show behaviour. The current level as inline style is the most appropriate.
Just put the condition on your _visible-_ class instead of using v-show. It makes no sense to have a hidden element with some _visible-_ classes anyway.
As @sylvainpolletvillard said, if you want to apply !important
you should create a class for it.
@posva v-hide does not apply a class to the element when hidden. If it did this would be a non-issue. Wouldn't a class have to be applied via v-bind? Seems like a contrived way to go about hiding an element and would make v-hide completely useless when doing responsive design in a popular css framework.
v-hide
doesn't exist but you can create your own using the v-show directive as a reference. You can even publish it to npm a post it here 😉
Yes, the class have to be applied with a v-bind
@posva Sorry I meant v-show
, sounds like I had a bit of a Freudian slip haha. That being said and expanding on what @sylvainpolletvillard said, is component overriding directives really something that should be widely supported? Seems to me something like that would be an edge-case that should be either handled by Vue's internal logic or some kind of decorator whereas something as common as responsive framework usage should be supported? I assume there's also a good reason why the directive doesn't apply a class for easy selecting, but I don't know enough to say what that is? Perhaps you can shed a bit of light on the reasoning?
By applying classes I mean something like this:
<div :class="{hide: hide}"></div>
.hide {
display: none !important;
}
Maybe a modifier to v-show
can come in handy v-show.important=""
It would still be !important
vs !important
. !important
is the nuclear bomb of CSS specificity: there is nothing above it. Betting on a double !important
conflict for the application layout is a terrible idea IMO.
I do not know the reasons why Bootstrap visible-
classes use !important
in the first place, but by making this decision, it implies that Bootstrap claims the priority on the element visibility state. Vue should not interfere in this priority war, otherwise we would have the opposite problem where a user wants to override the styles in CSS but can't because of Vue.
@posva Yeah I understood what that meant. Like I said before I thought that seemed like a contrived way to do it and would defeat the purpose of having v-show
for those that use responsive classes.
I'm remarking on the philosophy of the design choice. If the design is to allow components to override the show directive I argue that is a poor design choice if support for popular CSS frameworks is intended. This issue will return many times in the future from folks using responsive classes since it will simply look like v-show
is not working.
I agree with @codysherman in that Vue should take precedence over something like a responsive class since the model should represent a more accurate picture of display intent.
@sylvainpolletvillard correct me if I'm wrong, but wouldn't the !important
modifier bound directly to the element like how v-show
is currently implemented take precedence regardless? If we were talking about a class that was applied to the element then I think you would be right, but that's not the way Vue is implemented.
I do not know the reasons why Bootstrap visible- classes use !important in the first place, but by making this decision, it implies that Bootstrap claims the priority on the element visibility state. Vue should not interfere in this priority war
I can agree to that, but:
otherwise we would have the opposite problem where a user wants to override the styles in CSS but can't because of Vue.
Statically overriding a dynamic decision of Vue with important
in the CSS seems to be a strange idea was well.
I agree with @codysherman in that Vue should take precedence over something like a responsive class since the model should represent a more accurate picture of display intent.
I can agree to that but think we don't want to introduce this as a default behaviour as it would be a breaking change.
So we are left with @psova's suggestion of a modifier like v-show.important or telling people to build their own directive / use a class binding:
:class{'visible-xs': someCondition, hide: !someCondition}
@sylvainpolletvillard correct me if I'm wrong, but wouldn't the !important modifier bound directly to the element like how v-show is currently implemented take precedence regardless? If we were talking about a class that was applied to the element then I think you would be right, but that's not the way Vue is implemented.
@BrainBacon Yes it will, because inline style has the highest specificity
I can agree to that but think we don't want to introduce this as a default behaviour as it would be a breaking change.
[email protected] perhaps? Having a mid-term solution like v-show.important
would work as long as the documentation is highlighting this exact use case. Maybe a name like v-show.responsive
would be more appropriate?
I think this behavior should be default in the future if we're talking about breaking changes.
Statically overriding a dynamic decision of Vue with important in the CSS seems to be a strange idea was well.
I personnally use this for @media print queries. I have some layout handled with v-show
that I want to be always visible or hidden when printed. My usecase is a form composed of multiple steps, one visible at a time on computer, but they all need to be visible when printed. With this change, it won't be possible to do this anymore since you can't override inline !important
with media queries. I am sure there are other valid use cases where overriding in CSS is necessary.
Something like <div :class="{ 'hidden-lg': message === 'true' }">
looks like the right thing to do here.
Something like
<div :class="{ 'hidden-lg': message === 'true' }">
looks like the right thing to do here
Seems like a lot of added complexity for something that is very common. You're depending on every designer to think about the interaction between the responsive logic and the model logic.
I would say this is not Vue's problem, but Bootstrap's problem. It's Bootstrap using !important that forces everyone into this specificity war. If I were you I'd not use static CSS that has !important unless for very specific reasons like printing. And I don't think this is a common case.
Here is a pure CSS solution that might help anyone caught in this dilemma out:
*[style*="display: none"] {
display: none !important
}
@yyx990803 It could be a Bootstrap's problem, but at the same time Bootstrap also has reasons to use !important
on display properties.
Vue shouldn't change the default behaviour, and Bootstrap can't remove !important
from its utilities. But I still like @posva suggestion of adding an option like v-show.important
for those who want to use it.
Another option could be adding a new global configuration property for this:
# conditionalRenderingPriority
Type: boolean
Default: false
Usage:
Vue.config.conditionalRenderingPriority = true
Adds
!important
to inlinedisplay: none;
styles added byv-show
.
@codysherman that was cool
Thank you very much @gijo-varghese, I'm very glad that I was able to help out!
I know this is old, but I feel that I should add that it is not only Bootstrap's visability classes that interfer with v-show
, but all of their display classes! I think it is much less of an edge case for me to have an element with the d-flex
class that I want to show/hide with v-show
, and having something like v-show.important
as suggested above would be ideal for cases where such a conflict arises.
My current solution is to use class bindings to add Bootstrap's display class with the same condition as v-show
so it is removed when hiding the element:
<div v-show="someCondition" :class="{ 'd-flex': someCondition }">
<!--content-->
</div>
I will use a template to include the element with Bootstrap's 'visible-*' classes or "d-flex" class.
or you can put the "visible-*" class in v-bind:class like this:
<div :class="{'d-flex': show}" v-show="show">
<div class="border border-danger small-box"></div>
<div class="border border-danger small-box"></div>
<div class="border border-danger small-box"></div>
<div class="border border-danger small-box"></div>
</div>
<button @click="toggle_show()">toggle_show</button>
Here is an example.
Most helpful comment
Here is a pure CSS solution that might help anyone caught in this dilemma out:
*[style*="display: none"] { display: none !important }