CSS Modules - exclude class from being transformed - css

I'm using CSS modules and by far everything was working great.
We started to use external UI library along with our own one, so I'm writing components like this:
<div className={styles['my-component']}>
<ExternalUIComponent />
</div>
Assuming that the ExternalUIComponent has its own class that in the final CSS file looks like this external-ui-component, how can I make adjust this component styling from my css file? The below example does not work:
.my-component {
font-size: 1em;
}
.my-component .external-ui-component {
padding: 16px;
// Some other styling adjustments here
}

Please do not use inline styles as someone else suggested. Stay away from inline styles as much as you can because they can cause unnecessary re-renders.
You should use global instead.
.my-component {
:global {
.external-ui-component {
padding: 16px;
// Some other styling adjustments here
}
}
}
https://github.com/css-modules/css-modules#usage-with-preprocessors
Also, I recommend using camel case style names which is the preferred way for css-modules.
So your class name would be : .myComponent { ... }
And you can use it in your code as
<div className={ styles.myComponent } >
If you wanted to add more styles , you can use the array.join(' ') syntax.
<div className={ [ styles.myComponent, styles.anotherStyle ].join(' ') } >
This is cleaner!

Here's a shorter form in pure CSS (i.e. no preprocessor needed):
.my-component :global .external-ui-component {
// ...
}

Did you try inline styles for that component ?
https://reactjs.org/docs/dom-elements.html#style
const divStyle = {
color: 'blue',
backgroundImage: 'url(' + imgUrl + ')',
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}

Related

Styling an extended native element in ShadowDOM

I understand that in order to style elements from the ShadowDOM, the shadowDOM itself has to "know"
the element, thus be declared inside of it.
It works well for regular web components but i haven't found an answer to it weather it's the same for an extended
native element.
For example, I wanted to know if the code I wrote is the best way, i.e. the external p acting as container, or am i creating a redundant p element.
JavaScript:
class P_example extends HTMLParagraphElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.innerHTML = `
<style>
p{
background-color: orangered;
width: max-content;
}
</style>
<p><slot>Some default</slot></p>
`;
this.shadowRoot.append();
}
connectedCallback() {
//add styling class to the p element
}
}
customElements.define("omer-p", P_example, { extends: "p" });
HTML:
<p is="omer-p">Some sample text</p>

How do I reference an inner class?

I'm using Material UI styling. it's my first time using that platform and it will be my last time. but for now, I'm stuck with it. so I have a question. I have something like:
.map(section => (
<Section className={classNames(classes.section, section.class)}>
<div className={classes.content}>
...
</div>
</Section>
))
where section names generally look like Section1, etc. I then want to style so I'm trying this:
{
section: {},
Section1: {
backgroundColor: 'black',
'& img': { ... }
content: { border: '1px solid pink' }
}
}
but the pink border is not getting applied and I can't figure out why
it appears the images get styled as expected, I see this in the generated code:
.makeStyles-Section1-415 {
content: [object Object];
}
.makeStyles-Section1-415 img {
margin-left: 400px;
}
from which it's obvious that the MUI class generator doesn't know how to produce the inner class name. obviously '& .content' wouldn't work either as the actual class name generated will look something like makeStyles-content-415
so what is the correct incantation to make this work?
p.s.
obviously I can do something heinous like:
{
Section1Content: {}
}
but if that's the correct answer it's a powerful reason to rip this styling system out completely
the answer is:
Section1: {
'& $content': { border: '1px solid pink' }

StencilJS | Use CSS "+ Selector " in component

I am working on a web component library with StencilJS, and I have a problem using the CSS + Selector. I have a Breadcrumb web component, which will contain multiple breadcrumb items (web component as well). Every Breadcrumb item after the first item should add > smybol with ::before. Therefore I use the CSS + selector
df-breadcrumb.tsx
export class DFBreadcrumb {
render() {
return <ol class="breadcrumb">
<slot></slot>
</ol>
;
}
}
df-breadcrumb-item.tsx
export class DFBreadcrumbItem {
/**
* Link
*/
#Prop() link: string;
render() {
return this.link ? <li class="breadcrumb-item"><a href={this.link}><slot></slot></a></li> :
<li class="breadcrumb-item"><slot></slot></li>
;
}
}
test.html
<df-breadcrumb>
<df-breadcrumb-item link="#">Start</df-breadcrumb-item>
<df-breadcrumb-item link="#">Library</df-breadcrumb-item>
<df-breadcrumb-item>Item</df-breadcrumb-item>
</df-breadcrumb>
my css rule
.breadcrumb-item+.breadcrumb-item:before {
display: inline-block;
padding-right: .5rem;
color: #6c757d;
content: ">";
}
expected output: Start > Library > Item
current output: Start Library Item
I think this is not working cause Stencil ecapsulates my li tags and their direct parent is not the ol. I read something about using the :host() pseudo class, but could not got it working. Also I have set shadow: falsein my components.
You're right, the problem is the df-breadcrumb-item element.
A simple alternative would be to apply your CSS to the df-breadcrumb-item elements:
df-breadcrumb-item + df-breadcrumb-item:before {
display: inline-block;
color: #6c757d;
content: ">";
}
Alternatively you could add the arrow to the .breadcrumb-item element inside the df-breadcrumb-item component, either depending on a property or by manually checking if the #Element() is the last node.

CSS variables use in Vue

Is it possible to use pure CSS variables with Vue without having to link any stylesheets or use SASS/PostCSS? Unsure why I'm unable to get this to work in its most basic form.
<template>
<div id="test">
TEST
</div>
</template>
<style scoped>
:root {
--var-txt-color: #c1d32f;
}
#test {
color: var(--var-txt-color);
}
</style>
I know you highlighted "without having to link any stylesheet", but I run into the same issue and there is a simple option - use just one external css file and include it in your App.vue, then you can access the variables anywhere else, in scoped styles as well.
variables.css
:root {
--font-family: "Roboto", "Helvetica", "Arial", sans-serif;
--primary-color: #333a4b;
}
App.vue
<style>
#import './assets/styles/variables.css';
</style>
LandingView.vue
<style scoped>
#landing-view {
font-family: var(--font-family);
font-weight: 300;
line-height: 1.5em;
color: var(--primary-color);
}
</style>
This won't work as expected because of scoped attribute for stylesheet. Example above compiles into:
[data-v-4cc5a608]:root {
--var-txt-color: #f00;
}
And, as you understand, it will not target actual :root element.
It can be solved by:
Not using scoped attribute for this stylesheet. Notice that it may cause styles conflict with other variables declarations for :root element.
Using current component's wrapping element as root. If we declare variables this way:
.test {
--var-txt-color: #c1d32f;
color: var(--var-txt-color);
}
.test-child-node {
background-color: var(--var-txt-color);
}
Then it will can reuse variables for other elements of the same component. But still, it won't be possible to use declared variables inside child components without removing scoped, if it is the case.
Why not just use this?
<style scoped>
* {
--var-txt-color: #c1d32f;
}
</style>
The generated CSS is:
*[data-v-d235d782] {
--var-txt-color: #c1d32f;
}
This has been working for me.
I just discovered that it looks like this also works, using the "deep selector"
>>> {
--var-txt-color: #c1d32f;
}
Generated CSS is:
[data-v-d235d782] {
--var-txt-color: #c1d32f;
}
I think I like this method more.
One workaround is to define them under a non-scoped style element like the following. However one thing to note here is, these variables will be exposed to other Vue components as well.
<style>
:root {
--var-txt-color: #c1d32f;
}
</style>
<style scoped>
#test {
color: var(--var-txt-color);
}
</style>
Late answer - Here is a working example with css vars derived from standard vue structures.
<template>
<div>
<component :is="'style'">
:root {
--color: {{ color }};
--text-decoration: {{ textDecoration }};
--font-size: {{ fontSize }};
}
</component>
<p>example</p>
</div>
</template>
<script>
export default {
props:{
color: {
type: String,
default: '#990000'
}
},
data: function () {
return {
textDecoration: 'underline'
}
},
computed: {
fontSize: function (){
return Math.round(Math.random() * (5 - 1) + 1) + 'em';
}
}
}
</script>
<style>
p{
color: var(--color);
text-decoration: var(--text-decoration);
font-size: var(--font-size);
}
</style>
Starting from the top...
Vue must have 1 root element, so I needed a div tag in order to include a sample p tag. However, you can just use the component-is-style tag and get rid of the div and p tags. Note the need for extra quotations "'style'".
The normal vue style tag can be scoped or not - as needed.
Well, now you can use CSS variable injection.
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
font: {
weight: '800'
}
}
}
}
</script>
<style>
.text {
color: v-bind(color);
font-weight: v-bind('font.weight');
}
</style>
Those styles are also both reactive and scoped. There won't be any unintended inheritance issues. Vue manages the CSS variables for you.
You can take a look at the RFC here.

How do you add multiple browser specific values into a CSS style in React?

This is mainly to define browser specific values like this one for a given CSS property:
<div style="cursor: -moz-grab; cursor: -webkit-grab; cursor: grab;">Grab me!</div>
If I wrap it into object like this:
<div style={{
cursor: "-moz-grab",
cursor: "-webkit-grab",
cursor: "grab"
}}>Grab me!</div>
then you duplicate keys in an object (would fail in strict mode and would overwrite otherwise). And simply putting all values into single string doesn't seem to work either.
Figuring out browser with JS and then applying right value seems to be too much work.. Or is there a different approach to do this? Any ideas?
If you want to use inline styles and also get vendor prefixing, you can use a library like Radium to abstract the vendor prefixing for you.
By adding a #Radium decorator to your component, Radium will hook into the styles you pass to the component and automatically manage and prefix them.
var Radium = require('radium');
var React = require('react');
#Radium
class Grabby extends React.Component {
render() {
return (
<div style={style}>
{this.props.children}
</div>
);
}
}
var style = {
cursor: "grab" // this will get autoprefixed for you!
};
The best you could do is to create a css class with the cursor attribute, and add it to your component
.container {
height: 10px;
width: 10px;
}
.grab {
cursor: -moz-grab,
cursor: -webkit-grab,
cursor: grab,
}
Then in your react component:
var isGrabEnabled = true;
<div className={['container', (isGrabEnabled ? 'grab' : '')]}>Grab me!</div>

Resources