When scoped in Nuxt.js, child elements are not styled - css

I'm using v2 of Nuxt.js.
If css is loaded under the following conditions, no style will be set on the child elements.
Import scss file with style settings with style tag
Add scoped to the style tag above.
Below is a demo.
CodeSandBox
It can be confirmed that the style for the elements under header in /assets/style.scss is not set.
header {
background: #dddddd;
> ul { // not working
list-style: none;
padding: 0;
display: flex;
}
button { // not working
background: black;
color: white;
}
}
Is there a way to style child elements in the form of importing scss?
The main codes are as follows.
<template>
<div id="app">
<Header />
<HelloWorld />
</div>
</template>
<script>
import Header from "./components/Header";
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
Header,
HelloWorld,
},
};
</script>
<style lang="scss" scoped>
#import "./assets/style.scss";
</style>
// Header.vue
<template>
<header>
<ul>
<li>
<h1>{{ appName }}</h1>
</li>
<li>
<button>Sign in</button>
</li>
</ul>
</header>
</template>
// style.scss
header {
background: #dddddd;
> ul {
list-style: none;
padding: 0;
display: flex;
}
button {
background: black;
color: white;
}
}
.hello {
background: #efefef;
padding: 1rem;
}

Its CSS will apply to elements of the current component only. So you need to append below code
<style lang="scss" scoped>
#import "../assets/style.scss";
</style>
at Header.vue to make the css file effected.

Related

::v-deep is not working with v-dialog content-class (scoped scss)

I am trying to style content of the Vuetify dialog component. I use content-class prop and scoped styles to do that. What is the difference between the styles below? How can i make scss version work? Codesandbox.
<style lang="css" scoped>
>>> .dialog-content {
outline: 5px solid black;
}
</style>
<style lang="scss" scoped>
::v-deep .dialog-content {
outline: 5px solid black;
}
</style>
<template>
// ....
<v-dialog v-model="dialog" content-class="dialog-content">
// ....
</v-dialog>
// ....
</template>
As mentioned here, styles cannot be scoped because "the dialog is removed from the component's DOM and inserted just under the v-app component at the top-level of the application"
try:
<style lang="scss">
.dialog-content {
outline: 5px solid black;
}
</style>

How to override global CSS in a CSS module file?

Lets say in my global.css file of a Next.js project I have:
.flex {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
I also have a Layout.js component and a Layout.module.css file. The component looks like this:
import styles from "../styles/Layout.module.css";
const Layout = ({ children }) => {
return (
<div>
<div className={styles.navbar}>
<div className="flex">
<h1>Structured Safety</h1>
<nav>
<ul>
<li> Home </li>
<li> Demo </li>
</ul>
</nav>
</div>
</div>
</div>
);
};
export default Layout;
and the Layout.module.css is:
/* Navbar */
.navbar {
background-color: var(--primary-color);
color: #fff;
height: 70px;
}
.navbar ul {
display: flex;
}
.navbar .flex {
justify-content: space-between;
}
Structured like this, my .navbar .flex does not overwrite the global .flex class and split the h1 from the nav. How can I accomplish overwriting my global style from this component style?
Since .flex refers to a global class you'll need to use the :global selector to target it in your CSS module.
/* Layout.module.css */
.navbar :global(.flex) {
justify-content: space-between;
}
Or using an alternate syntax.
.navbar {
:global {
.flex {
justify-content: space-between;
}
}
}
/** CSS MODULE FILE **/
.classname :global(.globalClass) { css properties }
.classname {
:global {
.globalClass { css properties }
}
}
In NextJS and React when you
import styles from "__.css" the styles becomes a variable so you have to use it in your HTML for it to take effect.
Currently you're not using any styles from your Layout.module.css, if you want to use that css you would change your html to: <div className={styles.navbar}> and such..

Is there a way to style an element in React using the ID without using className?

I am converting an old website into React, and do not want to have to change all the CSS files that were previously coded. A lot of elements have their styles set currently by using an id. Is there a way to get className={styles["#topBar"]} to set the style correctly without having to delete the # and replacing it with a . in the CSS folder?
Since you are using CSS Modules you need to access the styles slightly differently. You need to import styles from 'Component.module.css'; and then declare your styles by referencing this imported object styles.MyClass or in your case since you have hyphens you need to use bracket notation styles["top-bar"]
Here is a working sandbox
//MyComponent.js
import styles from "./MyComponent.module.css";
export default function MyComponent() {
return (
<div id={styles["top-bar"]}>
<h2>My Component</h2>
<InnerComponent id="inner" />
</div>
);
}
function InnerComponent({ id }) {
return (
<div id={styles[id]}>
<h3>Inner Component</h3>
<p id={styles.para}>Styled Paragraph</p>
</div>
);
}
//MyComponent.module.css
#top-bar {
width: 90vw;
margin: 1rem auto;
padding: 1rem;
text-align: center;
background-color: LightPink;
}
#inner {
background-color: LightBlue;
text-align: left;
}
#para {
color: red;
}
Here's a quick snippet showing it working with IDs.
function MyComponent() {
return (
<div id="top-bar">
<h2>My Component</h2>
<InnerComponent id="inner" />
</div>
)
}
function InnerComponent({id}) {
return (
<div id={id}>
<h3>Inner Component</h3>
</div>
)
}
ReactDOM.render(<MyComponent />, document.getElementById('App'));
#top-bar {
width: 90vw;
margin: 1rem auto;
padding: 1rem;
text-align:center;
background-color: LightPink;
}
#inner {
background-color: LightBlue;
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="App"></div>

How to overwrite the vue-bootstrap styles in b-modal

I tried to change the background-color in b-modal -> in .modal-header using bootstrap-vue. But the vue doesn't see my styles and I don know why :/
here is the code. I follow by answer in link
HTML:
b-modal(id="card-1" title="CARTÃO DE CRÉDITO" :modal-class="myclass" header-text-variant="light")
VUE
export default {
data: {
myclass: ['myclass']
},
}
CSS
.myclass > .modal-dialog > .modal-content > .modal-header {
background-color: #da2228 !important;
color: white;
}
But I still doesn't see the results. Modal header is white. Any ideas why?
You're probably using a scoped style tag in your .vue file.
If you are, then you need to use a deep-selector to properly target the subcomponent.
The selectors are /deep/, >>> or ::v-deep.
In the below example i use /deep/, but the others should work for you as well.
You can also use the header-class prop on b-modal to directly add the class to the header if you wish.
<template>
<b-modal header-class="my-class">
<template #modal-header>Header</template>
Hello
</b-modal>
<b-modal modal-class="my-second-class">
<template #modal-header>Header</template>
Hello
</b-modal>
</template>
<style scoped>
/deep/ .my-class {
background: black;
color: white;
}
/deep/ .my-second-class > .modal-dialog > .modal-content > .modal-header {
background: black;
color: white;
}
</style>
You can use content-class="your-class" in the vue bootstrap modal.
<b-modal id="myModal" content-class="your-class" title="BootstrapVue">
Body Content
</b-modal>
Or else it is difficult to style the modal cuz the normal class="" does not apply to the code.

bootstrap-vue change the position of <b-modal>

By default <b-modal> shows on top of the page. When attribute centered is added to the tag. It is centered.
However, I would like to show the modal with a certain amount of gap under the top of the page.
The Modal is shown when the home page is opened.
AppModal.vue
<template>
<b-modal ref="thisModalRef" :modal-class="my-modal" size="lg" hide-header hide-footer no-close-on-backdrop hide-header-close>
//...
</b-modal>
</template>
<script>
export default {
data () {
return {
mymodal: ['mymodal']
}
},
methods: {
hideModal () {
this.$refs.thisModalRef.hide()
},
showModal () {
this.$refs.thisModalRef.show()
}
}
}
</script>
<style scoped>
.mymodal > div {
position: absolute;
top: 300px;
right: 100px;
background-color: yellow;
}
</style>
AppHome.vue
<template>
<div>
// omitted
<AppModal ref="modalRef"></AppModal>
</div>
</template>
<script>
import AppModal from './AppModal'
export default {
components: {
AppModal
},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
showModal: function () {
this.$refs.modalRef.showModal()
}
},
mounted () {
this.showModal()
}
}
</script>
<style scoped>
// ommitted
</style>
html source related to modal
<div id="__BVID__16___BV_modal_outer_">
<div id="__BVID__16" role="dialog" class="modal fade show d-block mymodal" style="padding-right: 15px;">
<div class="modal-dialog modal-lg">
<div tabindex="-1" role="document" aria-describedby="__BVID__16___BV_modal_body_" class="modal-content">
<!---->
<div id="__BVID__16___BV_modal_body_" class="modal-body">
// ommitted
</div>
<!---->
</div>
</div>
</div>
<div id="__BVID__16___BV_modal_backdrop_" class="modal-backdrop fade show"></div>
</div>
As you can see, mymodal class is correctly applied. But the div .modal-dialog does not have the css properties I give it.
the real css properties found in dev tools
.modal-dialog {
position: relative;
width: auto;
margin: 0.5rem;
pointer-events: none;
}
I tried adding a custom class to <b-modal> and style it. Nothing worked.
Please help.
If you want to put the modal into the specific position, below is my solutuon:
add specific class to <b-modal> by its props=modal-class
then add your styles into myclass > div
You can look into the github (line#:176), Bootstrap-vue will place one div.modal-content(including header/body/foot) into one div with class="modal-dialog" which is the direct child of root.
That is why above solution use the css selector = .myclass > div.
If you look into the dom tree: the structure of one bootstrap-vue modal will be:
one root div (myclass will be added into here) -> one div with modal-dialog -> one div with modal-content -> header/body/footer
Below is one sample: (I put different background-color for modal-dialog, modal-content.)
app = new Vue({ //not vue, it is Vue
el: "#app",
data: {
myclass: ['myclass']
},
methods: {
showModal: function(){
this.$refs.myModalRef.show()
}
}
})
.myclass > div {
position:absolute !important;
top: -10px !important;
left: -10px !important;
background-color:yellow !important;
}
.myclass > .modal-dialog > .modal-content {
background-color:red !important;
}
<!-- Add this to <head> -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css"/>
<!-- Add this after vue.js -->
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<script src="//unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-button #click="showModal">
Open Modal
</b-button>
<b-modal ref="myModalRef" :modal-class="myclass" size="lg">
<h2>Test</h2>
</b-modal>
</div>
I use
<b-modal
body-class="modalcart"
ref="addToCart"
id="addToCarModal"
hide-footer
hide-header
>
<b-container class="text-center modal-product-content">
<img class="modal-image" src="~/assets/images/add-to-cart.png" alt=""/>
and:
<style lang="scss" scoped>
/deep/ .modalcart {
font-family: 'poppins-bold';
/deep/ .modal-product-content {
padding: 3rem;
margin: 0 auto !important;
/deep/ .modal-image {
height: 150px;
margin-bottom: 2rem;
}
}
...
}
</style>
and work! thanks
Keep in mind that not work without body-class and /deep/
I use node-sass, vue 3, vue-loader 15
Maybe you could try with something like margin-top: 100px.
I think it's because the #media breakpoint of Bootstrap. Then, in <style> you just override it.
#media (min-width: 576px) {
.modal-dialog {
margin: .5rem auto;
}
}

Resources