Scoped css class with elements - css

I use vue with vuetify. I have to use sass to override the style of vuetify components.
With the following code I want to update the style of my text field.
<style scoped lang="scss">
.center {
input {
text-align: center;
}
}
</style>
Without the scope attribute it works. But how do I make it work and only apply the current component?
<v-text-field v-model="myText" class="center" #input="onTextInput" />
Thanks

For Vue2 you need to add ::v-deep before the class.
Ex:
::v-deep .target-class {
background-color: #000;
}
For Vue3
:deep(.target-class) {
background-color: #000;
}

Related

Nuxt CSS properties declared on :root selector are not found

I have a Nuxt 2 app and I'd like to create a component with a <style> tag like the following, using CSS properties for styling.
The goal is to define a default CSS property in the component that can be overridden from outside.
However, when I try this method, the default values don't seem to work at all.
<style lang="scss" scoped>
:root {
--default-badge-color: linear-gradient(90deg, #1717ff 0%, #bc29e0 92%);
--default-badge-text-color: #fff;
--default-badge-font-size: 1.6rem;
--default-badge-padding: 0.6rem 1rem;
--default-badge-border-radius: 16px;
}
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--badge-padding, var(--default-badge-padding));
border-radius: var(--badge-border-radius, var(--default-badge-border-radius));
background: var(--badge-color, var(--default-badge-color));
color: var(--badge-text-color, var(--default-badge-text-color));
font-size: var(--badge-font-size, var(--default-badge-font-size));
text-align: center;
}
</style>
Do I have the wrong approach for the syntax?
EDIT: I corrected to padding: var(--badge-padding, var(--default-badge-padding)). But the CSS properties are still not found except I define them inside .badge.
It doesn't really make sense to scope :root, which is intended to select the root of the document with higher specificity than the html selector. That would be like scoping a style for <body>.
Perhaps you're hoping :root was a selector for the current component's root element (like :host is for Shadow DOM), but there's no such pseudo-class in Vue. An alternative is to apply your own class to the component's root element, and use that as a selector:
<template> 👇
<div class="my-root">
<div>...</div>
<div class="badge">...</div>
</div>
</template>
<style scoped>
👇
.my-root {
/* CSS custom properties */
}
.badge {
/* styles using the CSS custom properties above */
}
</style>
On the other hand, if you really are trying to add CSS custom properties to the document root from within <style scoped>, you can use the :global() pseudo-class function on :root:
<style scoped>
:global(:root) {
/* CSS custom properties */
}
.badge {
/* styles using the CSS custom properties above */
}
</style>
demo 1
Or a separate global <style> block just for :root:
<style>
:root {
/* CSS custom properties */
}
</style>
<style scoped>
.badge {
/* styles using the CSS custom properties above */
}
</style>
demo 2

Unable to apply simple CSS to an angular Materials element

Here's the Stackblitz.
I'm trying to apply the CSS color: blue to the div with class mat-button-toggle-label-content, but its not getting applied.
A similar CSS is getting successfully applied to a parent element called mat-button-toggle-group.
Just apply color to mat-button-toggle and keep it inside mat-button-toggle-group
Working stackblitz
mat-button-toggle-group {
background-color: orange;
mat-button-toggle {
color: blue;
}
}
You can apply the style to .mat-button-toggle-label-content but you need to break Encapsulation.
Component styles are encapsulated. You can't access component's styles(classes, ids) from outside of the component. You need to pierce into that component and inject the styles like below
Note: /deep/ is deprecated and no more recommended. So you can go with above approach. And for more details check Component Styles
mat-button-toggle-group {
background-color: orange;
/deep/ .mat-button-toggle-label-content {
color: blue;
}
}
There are many reason for that !
Your CSS may not be inserted properly into code
The order of material design CSS take over the order of CSS
My solution is that you may need to put !important after color: blue;
it is : color: blue !important;
Just move it to styles.scss and it will work Stackblitz.

Hide input field from vuejs-datepicker

I am using vuejs-datepicker in one of my vue project. I want to hide the default input and show the Calendar when user press a button. I am trying to have the <datepicker/> inside a div apply css for the div so that I can hide it.
<div class="datePickerDiv">
<datepicker class="date" ref="datepick"></datepicker>
</div>
<style scoped>
.datePickerDiv {
position: relative;
float: left;
margin-top: -40px;
}
.datePickerDiv input {
border: none;
background: transparent;
}
</style>
But its not working as I expect. Sample https://codesandbox.io/s/relaxed-sea-qfuix?file=/src/components/HelloWorld.vue:742-910
You need to use the >>> combinator in order to deeply select the input tag:
.datePickerDiv >>> input {
border: none;
background: transparent;
}
This is because you're using the scoped attribute on your style tag. scoped will only work to apply styling to child components directly referenced in your current Vue component. In this case, datepicker is creating its own child input which will not be affected by the style, unless you use the deep selector shown above.
For applying style in your date picker tag, use input-class instead of only class. The styling does not work on the default scoped style tags, so add another style tag beneath your scoped style tag like follows:
<style scoped>
---your scoped Styles ----
</style>
<style >
-- Apply your unscoped style over vue date picker here ---
</style>
Example
<datepicker input-class="date" ref="datepick"></datepicker>
<style>
.date {
display: none !important;
}
</style>
Add prop input-class with class hide-input. This will apply the hide-input class to the input element. Read more about props here.
<datepicker input-class="hide-input"></datepicker>
.hide-input{
display: none !important;
}

Working with nested selectors & vuejs css modules

Is it possible to work with nested css selectors when using vuejs css modules?
For example, I want to scope this css (so that id does not affect child components):
.list {
...
.item {
...
}
}
In the documentation I could see only not-nested examples, but is it at all convenient, since I'll need then name them like .list-item which resembles BEM. But if I use BEM there is no point in using css modules, is there?
Yes, it's possible to work with nested css selectors so they will not affect child components; use css modules.
You need to use a preprocessor to enable nesting, either LESS or SASS.
If using Single File Components your component would look something like this
<template>
<ul :class="$style.list">
<li :class="$style.item"></li>
</ul>
</template>
<!-- Or lang="less" -->
<style module lang="scss">
.list {
...
.item {
...
}
}
</style>
Yes, nesting css selectors is called using scss. You will have to setup scss.
Example make your style tag in the vue component:
<style scoped lang="scss">
The scoped attribute tells it to apply only to this component.
In regards to bem you can do stuff like this in scss:
.list {
//styles-a
&-item {
//styles-b
}
}
which will convert to this in css:
.list {
//styles-a
}
.list-item {
//styles-b
}
If you want, for example, override CSS class of some UI library in Vue you can use :global keyword. Let's say you have a n-dropdown component from Naive UI library. And you want to customize it with overriding its native very deeeeeply nested n-dropdown-option-body__prefix--show-icon CSS class only in current component using CSS modules. Here is how you can do it:
<template>
<n-dropdown :class="$style.menu">
</n-dropdown>
</template>
<style module>
.menu:global.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
margin-left: 33px;
margin-right: 19px;
}
</style>
In the end you will get selector which looks something like this
.MobileNavMenu_menu_NhSka.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
margin-left: 33px;
margin-right: 19px;
}
So all classes after :global keyword will be untouched by module manipulations.
If .n-dropdown-menu should be a child of menu then :global should have a whitespace from both sides:
.menu :global .n-dropdown-menu
Vue will remind you about it with horrible crash

How to style :root based on Custom Element Attribute

Update: See: How to style :root without !important using proper specificity
Is it not possible?
This Style rule is totally ignored
You forgot the parenthesis to :host():
elem.attachShadow({mode: 'open'})
.innerHTML = `
<style>
:host([player="X"]) {
display: inline-block;
background: red;
padding 1em;
}
</style>
Hello World`
<game-toes id=elem player="X"></game-toes>

Resources