Nuxt how to override global css for a page - vue.js

I have a project with multiple layouts, I have added the CSS globally in nuxt.config.js file like this:
css: [
'#/assets/plugins/fontawesome-free/css/all.min.css',
'#/assets/plugins/ionicons/css/ionicons.min.css',
'#/assets/plugins/feather/feather.css',
'#/assets/css/style.css',
'#/assets/css/custom-style.css',
'#/assets/css/skins.css',
]
but I want for just 1 layout to remove all css imported because the file being served is a static HTML file with all the styles inline.
Is this possible in nuxt and if not, what is the best possible workaround?

You could add the css files in your layout in a normal style block and not in nuxt.config.js.
<style lang="scss">
#import ...;
</style>
Then you can use another layout without these css files.

Remove the scope from your style on the .vue file where you want to override the global style:
<style s̶c̶o̶p̶e̶d̶>
.ProseMirror p {
color: rgb(236, 10, 10);
}
</style>
I wonder too, if you would be better off creating new vue layout files in the layout folder and applying those styles to the pages you want to affect globally, instead of pulling the css through nuxt.config.js file. Then, on the specific page that you want to override the global style, just remove the scope as I mention above. Just a thought.

Related

How to build web component with styling library using vite and vue 3?

I am able to build vue web component and load it in other pages, but I can't find document how to correctly include a UI framework. It seems the web component is under shadowDOM and import css using style tag won't work.
(Add the CDN link in the template and style is applied)
Any hint on any framework, Vuetify or Ant Design or Tailwind CSS will be appreciated.
Similar question: Vuetify build as Web component style not showing
Using custom elements without Shadow DOM is trivial. Just add like the way you do traditionally. However, with Shadow DOM, things are tricky. Only inheritable CSS styles pass through the Shadow DOM. Everything else is blocked. No straight forward integration with existing design systems (Vuetify, Ant, etc.) is not directly possible if that library is only exposing global CSS.
If the design system or a component library is exposing styles i.e. css files for individual components, then you can that with some effort.
The best solution is to use constructable stylesheet. You can use a bundler like Webpack to load the stylesheet for individual component (if and only if it is provided) as a string and feed it to the stylesheet constructor method as illustrated here.
// Read SCSS file as a raw CSS text using Webpack/Rollup/Parcel
import styleText from './my-component.scss';
const sheet = new CSSStyleSheet();sheet.replaceSync(styleText);
// Use the sheet inside the web component constructor
shadowRoot.adoptedStyleSheets = [sheet];
However, Firefox and Safari are yet to implement it.
If you need a fallback, then there are ways that are not so clean. Approach is same. Import the CSS/SCSS as a string and using the template literal, add it to the element's inner style tag.
import styleText from 'ant/button.css';
class FancyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<!-- Styles are scoped -->
<style>
${styleText}
</style>
<div>
<p>Hello World</p>
</div>
`;
}
}
customElements.define('fancy-comp', FacyComponent);
This all relies on the assumption that ant/material/veutify is exposing styles as individual files instead of one global file.
Alternately, the browsers have started supporting the link tag inside the Shadow DOM. But again it is really useful if you have styles for individual components. Read more about that here.

Headless UI component will not take style

I'm currently playing around with Headless UI and I can't seem to style any of the components.
This is the code in my tabs file
<template>
<TabGroup>
<TabList class="bg-blue-900/20 rounded-xl">
<Tab>Products Information</Tab>
<Tab>Find Offices Nearby</Tab>
<Tab>Requirements</Tab>
</TabList>
<TabPanels>
<TabPanel>Content 1</TabPanel>
<TabPanel>Content 2</TabPanel>
<TabPanel>Content 3</TabPanel>
</TabPanels>
</TabGroup>
</template>
<script>
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '#headlessui/vue'
export default {
components: {
TabGroup,
TabList,
Tab,
TabPanels,
TabPanel,
},
}
</script>
It's either of these problems
Tailwind CSS is not installed or configured properly so you cannot use Tailwind CSS classes like 'rounded-xl'.
'bg-blue-900/20' is not an inbuilt tailwind CSS class, so either customize color in tailwind or use inbuilt colours like 'bg-blue-400', 'bg-blue-500', etc
Tailwindcss v2.1 introduced JIT mode that generates styles on-demand.
You need to enable jit mode to use such classes like bg-blug-900/20.
You can see how to do that in official doc

VueJS - How to remove classes while building?

I'm writing scoped SCSS. This creates like this html.
<nav data-v-8998d9f4 class="nav">
....
</nav>
.nav[data-v-8998d9f4] {
...
width: 100%;
}
But I would like to remove class names while building. So should be like this:
<nav data-v-8998d9f4>
....
</nav>
[data-v-8998d9f4] {
...
width: 100%;
}
Is there any way to do this? I choose my class names sloppy and I don't want them to appear. Also, classes are completely unnecessary when writing scoped.
After reviewing this question and my first answer again i have to admit that my first answer was wrong.
This is actually a bad idea. When removing the selector all of the elements inside that component will have the same styling, because that data-hash attribute is the same for the whole component. Also as far as i know there is no way to modify the naming of scoped styling in vue.js
However if you want the freedom to change the naming of the generated classes you might want to use CSS modules instead of scoped styling.
Here is a good explanation about that: https://www.netguru.com/codestories/vue.js-scoped-styles-vs-css-modules
Also theres a section in the vue-cli documentation for that:
https://cli.vuejs.org/guide/css.html#css-modules
Another alternative would be to use none of the above and instead go for something like BEM where you begin with your components name as the block. This way your style is scoped aswell and the readability is a lot better.
With my initial answer i have confused css modules with scoped styling, but for the record this is my initial answer:
Yes this is possible.
take a look at the following webpack config:
// webpack.config.js
{
module: {
rules: [
// ... other rules omitted
{
test: /\.scss$/,
use: [
'vue-style-loader',
{
loader: 'sass-loader',
options: {
// enable SCSS Modules
modules: true,
// customize generated class names
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
source: https://vue-loader.vuejs.org/guide/css-modules.html#usage
localIdentName is what you are looking for. you could change this to '[hash:base64:8]'
However i personally think this makes your css unnecessarily verbose. Debugging something in the browser might be a pain like that.

How to inherit svg's css properties using vue svg loader

I am using vue-svg-loader to use my svg files as a component in Vue project. When I am rendering those svgs I am losing default css properties that are inside of the svg file. I can add those css properties inside of my component where I am rendering svg files, but that kind of violates the idea of reusable components since each svg file has its own property. Is there a way to inherit their css?
'''
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:none;}
.st2{fill:#FFFFFF;stroke:#000000;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:10;}
.st3{font-family:'ArialMT';}
.st4{font-size:32px;}
</style>
<font horiz-adv-x="2048">
'''
Likely what is happening is that all of your SVG files use the same class names (st0, st1, etc). They are overriding each other. You'll need to:
manually rename the classes in each file, so they use different names, or
That file looks like it came from Illustrator. Assuming they all did, then load the SVGs back into Illustrator, and re-export them. This time change which method AI uses to set the element styles. I don't have AI handy right now, but there will probably be three options (I don't recall exactly what they are called):
Internal CSS - what the file above is using
Style attributes - uses the style="..." attrinbute
Attributes - uses attributes like fill="#ff0000"
If you need to style the SVGs with CSS in your page, you'll probably want to use the last option. That's because style attributes have a higher priority than CSS, so you would need to use the CSS !important flag, which is not generally recommended.
I've found that the vue-svg-loader documentation is pretty thin, mainly because all its configuration is done via the svgo library. There are some clues in this FAQ, which shows you how to customise the svgo configuration in your webpack config.
So maybe you want something like this in your vue.config.js file:
module.exports = {
chainWebpack: (config) => {
const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule
.use('babel-loader')
.loader('babel-loader')
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader')
.options({
svgo: {
plugins: [
addClassesToSVGElement: {
classNames: ["foo", "bar"],
}
],
},
});
},
};

Non-scoped styling in components applied only once when switching routes

Vue.js documentation for Scoped CSS mentions that
You can include both scoped and non-scoped styles in the same component
I built the example application for vue-router and used two single file components instead of the string templates of the example - the rendering is as expected.
I then tried to apply both scoped and non-scoped styles in the components. In the first one I have
<style scoped>
div {
color: white;
background-color: blue;
}
</style>
<style>
body {
background-color: green;
}
</style>
and the second one
<style scoped>
div {
color: white;
background-color: red;
}
</style>
<style>
body {
background-color: yellow;
}
</style>
The idea is to have the whole body background switch when choosing a specific route.
The scoped styles are OK - they change depending on the route.
The non-scoped ones do not (screenshots are from Chrome Dev Tools):
on initial application load (non routed yet) the background is white (which is OK - this is the default one and there is no route for /).
when choosing a route, the style for the body is applied correctly (say, green from the first component)
when switching routes and loading the second component the background changes to the new color, it looks like from Chrome Dev Tools that the current style for background-color is overwritten. All the other components elements are correctly rendered (content and scoped styling)
further switches keep the same background (and again, other elements of the relevant component are rendered correctly). There are no changes in Chrome Dev Tools (the last view above is unchanged)
In other words, it looks like the style is stacked and previously overwritten properties are not updated Is this expected behaviour?
I opened a bug report for this and it ended up being expected behaviour. The summary from the report comments:
Thorsten Lünborg:
Yes, this is expected. Vue (or rather, webpack) does not insert and
remove these styles, as you seem to think. They are injected into the
head once the component renders, and never removed.
A common pattern is to extarct all CSS into a single .css file in
production, which would have the same result.
My summary in the context of the question:
initially (no route, no component rendered) nothing was injected
the first component is rendered on route switch, its style is injected
the second component is rendered on route switch, its style is injected and overwrites the previous style
further route switches do not inject anything as each component was already rendered once. The last style used therefore stays as the authoritative one.
I will therefore fallback on binding the body class to the current component's data