I'm using styled-components with React. I'd like to remove the default bottom margin for all <p>s, so in my main App component I added a nested selector:
const App = styled.div`
p {
margin: 0;
}
`
However, I do want to be able to add margin to some <p>s, e.g.:
const SpacedP = styled.p`
margin-bottom: 10px;
`
But when I try to use a <SpacedP> within <App>, the resulting App CSS is more specific than the SpacedP CSS, so my <SpacedP>s still have no margin! (App CSS compiles to ${App} p { ... }, while SpacedP only has one prefix, ${SpacedP} { ... }).
Is there a common pattern for situations like these? I don't really like the &&& specificity workaround suggested here, seems ugly and hacky; hoping there's a more common setup that I'm missing.
Thanks!
On a project we have custom templates string to abstract styled-components functions. For example, we have templates string for the media-queries that look like this one:
// Definition
const for1080p = (...args) => css`
#media (min-height: 1080px) {
${css(...args)}
}
`;
// Usage
const Logo = styled.div`
width: 200px;
${for1080p`
width: 300px;
`}
`;
We made this choice because it keeps the original styled syntax. It is also nicely formated by prettier.
Our main problem today is that we don't know how to analyse with stylelint our CSS that are inside a custom template string.
For example:
const Logo = styled.div`
widht: 200px; /* <--- Unexpected unknown property "widht" */
${for1080p`
widht: 300px; /* <--- No error detected :( */
`}
`;
Do you know how to do this?
The CSS-in-JS parser built into stylelint doesn't yet support interpolation tagging, and therefore can't know that the second widht: 300px; is a declaration.
Until that support is added, you can either:
see how much mileage you get from the styled-components stylelint processor and its support for interpolation tagging
use standard CSS constructs, rather than custom templates string, for things like #media
I think there is a way to do it now with https://github.com/styled-components/stylelint-processor-styled-components and as documentation states -
Combining with moduleName, importName and strict, you can tell the
processor what kinds of tagged template literals to lint.
{
"processors": [["stylelint-processor-styled-components", {
"moduleName": "styled-components",
"importName": ["default", "for1080p"], <---- here
}
That stuff wasn’t tested by me, but I think it suppose to do the trick
It might be relevant to note that I'm using Next.js, which was already being finicky with css files (having to npm install #zeit/next-css just to be able to import css files into javascript pages).
So there's a specific Panel element from a third party API that doesn't have an attribute for setting background image. It should be fine, though, because they provide css mappings for all their elements, right?...
Apparently not, because when I add background-image: url('img.png'); (the css and picture are in the same directory) to
.ais-Panel-header {
margin-bottom: 0.5rem;
padding-bottom: 0.5rem;
font-size: 5rem;
font-weight: bold;
text-align: center;
text-transform: uppercase;
border-bottom: 1px solid #f1b68a; }
I get the following error
The panel works with any background-color. Anyway, the problem isn't element-specific, I've tried image filepaths with other elements like the body background and run into the same error. Unfortunately, since this time I'm dealing with a React component, I can't just weasel a <body background="path"> in.
Does anyone have any experience with this or any clue as to why this is happening and potential workarounds?
next-css don't handle image loading
const withCSS = require("#zeit/next-css");
module.exports = withCSS({
webpack: config => {
config.module.rules.push({
test: /\.(png|jpg)$/,
use: {
loader: "url-loader"
}
});
return config;
}
});
I'm currently developing a web application in Outsystems in which I have the need to customize the CSS, in which I'm using variables. I need to guarantee the app works cross-browser, including in Internet Explorer. IE doesn't support CSS variables, as you can see in the picture below from this source.
Since I have to use CSS variables, is there any workaround for the usage of variables in IE?
Yes there is a way, the same way you make any css compatible: use a specific css fallback that is supported by the browser.
body {
--text-color: red;
}
body {
color: red; /* default supported fallback style */
color: var(--text-color); /* will not be used by any browser that doesn't support it, and will default to the previous fallback */
}
This solution is incredibly redundant and 'almost' defeats the purpose of css variables....BUT it is necessary for browser compatibility. Doing this would essentially make the css variables useless but I implore you to still use them because it will serve as an important reminder to the fact that these values are referenced elsewhere and need to be updated in all cases, otherwise you forget to update every related occurrence of 'color' and then you have inconsistent styling because relevant css values are out of sync. The variable will serve more as a comment but a very important one.
There is a polyfill, which enables almost complete support for CSS variables in IE11:
https://github.com/nuxodin/ie11CustomProperties
(i am the author)
The script makes use of the fact that IE has minimal custom properties support where properties can be defined and read out with the cascade in mind.
.myEl {-ie-test:'aaa'} // only one dash allowed! "-"
then read it in javascript:
getComputedStyle( querySelector('.myEl') )['-ie-test']
From the README:
Features
handles dynamic added html-content
handles dynamic added , -elements
chaining --bar:var(--foo)
fallback var(--color, blue)
:focus, :target, :hover
js-integration:
style.setProperty('--x','y')
style.getPropertyValue('--x')
getComputedStyle(el).getPropertyValue('--inherited')
Inline styles: <div ie-style="--color:blue"...
cascade works
inheritance works
under 3k (min+gzip) and dependency-free
Demo:
https://rawcdn.githack.com/nuxodin/ie11CustomProperties/b851ec2b6b8e336a78857b570d9c12a8526c9a91/test.html
In case someone comes across this, has a similar issue where I had it set like this.
a {
background: var(--new-color);
border-radius: 50%;
}
I added the background colour before the variable so if that didn't load it fell back on the hex.
a {
background: #3279B8;
background: var(--new-color);
border-radius: 50%;
}
Yes, so long as you're processing root-level custom properties (IE9+).
GitHub: https://github.com/jhildenbiddle/css-vars-ponyfill
NPM: https://www.npmjs.com/package/css-vars-ponyfill
Demo: https://codepen.io/jhildenbiddle/pen/ZxYJrR
From the README:
Features
Client-side transformation of CSS custom properties to static values
Live updates of runtime values in both modern and legacy browsers
Transforms <link>, <style>, and #import CSS
Transforms relative url() paths to absolute URLs
Supports chained and nested var() functions
Supports var() function fallback values
Supports web components / shadow DOM CSS
Watch mode auto-updates on <link> and <style> changes
UMD and ES6 module available
TypeScript definitions included
Lightweight (6k min+gzip) and dependency-free
Limitations
Custom property support is limited to :root and :host declarations
The use of var() is limited to property values (per W3C specification)
Here are a few examples of what the library can handle:
Root-level custom properties
:root {
--a: red;
}
p {
color: var(--a);
}
Chained custom properties
:root {
--a: var(--b);
--b: var(--c);
--c: red;
}
p {
color: var(--a);
}
Nested custom properties
:root {
--a: 1em;
--b: 2;
}
p {
font-size: calc(var(--a) * var(--b));
}
Fallback values
p {
font-size: var(--a, 1rem);
color: var(--b, var(--c, var(--d, red)));
}
Transforms <link>, <style>, and #import CSS
<link rel="stylesheet" href="/absolute/path/to/style.css">
<link rel="stylesheet" href="../relative/path/to/style.css">
<style>
#import "/absolute/path/to/style.css";
#import "../relative/path/to/style.css";
</style>
Transforms web components / shadow DOM
<custom-element>
#shadow-root
<style>
.my-custom-element {
color: var(--test-color);
}
</style>
<div class="my-custom-element">Hello.</div>
</custom-element>
For the sake of completeness: w3c specs
Hope this helps.
(Shameless self-promotion: Check)
Make a seperate .css file for your variables. Copy/paste the contents of the variable.css file to the end of your main.css file. Find and replace all the variable names in the main.css file to the hex code for those variables. For example: ctrl-h to find var(--myWhiteVariable) and replace with #111111.
Side note: if you keep the :root{ } in the main.css file and just comment it out, you can use that to track those hex codes later if you want to update your fallback colors.
Another way to do it is declaring colors in a JS file (in my case I'm using react) and then just use the variable you defined in the JS file.
For example:
in globals.js
export const COLORS = {
yellow: '#F4B400',
yellowLight: '#F4C849',
purple: '#7237CC',
purple1: '#A374EB',
}
in your file
import { COLORS } from 'globals'
and then just use COLORS.yellow, COLORS.purple, etc.
body {
--text-color : red; /* --text-color 정의 */
}
body {
color: var(--text-color, red); /* --text-color 정의되지 않으면 red로 대체됨 */
}
body {
color: var(--text-color, var(--text-color-other, blue));
/* --text-color, --text-color-other 가 정의되지 않으면 blue로 대체됨 */
}
There is no way yet in "normal" css but take a look at sass/scss or less.
here is a scss example
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
I recommend setting your css variables as sass variables, then using sass interpolation to render the color in your elements.
:root {
--text-color: #123456;
}
$text-color: var(--text-color);
body {
color: #{$text-color};
}
If im not wrong there is a workaround, the CSS #ID Selector. Which should work for IE > 6 I guess.. So you can
.one { };
<div class="one">
should work as
#one {};
<div id="one">
I am using css modules, however a library I use in a component to append tweets with JavaScript adds some elements to my component in the following structure:
<div class='user'></div>
<div class='tweet'></div>
I want to now style these elements in my css module for the component, as follows:
MyComponent.css
.user {
/* styles */
}
.tweet {
/* styles */
}
However of course now my .user class changes to .MyComponent__user___HZWfM due to the hash naming in the webpack loader.
How can I set a global style in my css module?
According to the css modules docs, :global switches to the global scope for the current selector. e.g.
:global(.example-classname)
So this should work:
:global(.tweet) {
text-align: left;
}
:global(.user) {
text-align: left;
}
Or define a global block
:global {
.tweet {
text-align: left;
}
.user {
text-align: left;
}
}
Can use module class with static class with this way.
myStyle.module.css
.moduleClass_g1m59k:global(.StaticClass) {
background-color: orange;
}
Output will generate like this
.moduleClass_g1m59k.StaticClass {
background-color: orange;
}
Many people have struggled with this and there doesn't seem to be any one agreed upon solution. The one I have settled with involves some tweaking of your bundler and specifically addresses the need to import libraries as-is without having to wrap them or edit them manually.
In my webpack config I have set it to scan all files ending css except those within the 'node_modules' and 'src/static' folders. I import my libraries from here and they dont suffer the classname transforms so I am free to use regular classnames for global css and the className={styles.element} convention as usual for modular css (which will compile down to .component_element__1a2b3 or something similar).
Here is an example of a working production webpack config with this solution:
http://pastebin.com/w56FeDQA