Am using styled components in React. Whenever i write the styles in styled component and if loads the application in the browser am getting some random classes name in the elements tab of developer tools. I just want to know whats happening behind the scene?
const Button = styled.a`
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
`
render(
<div>
<Button
href="https://github.com/styled-components/styled-components"
target="_blank"
rel="noopener"
primary
>
GitHub
</Button>
<Button as={Link} href="/docs">
Documentation
</Button>
)
if we inspect and check the element in the developer tools , i can able to see some random classes display like as follow;
<a
href="https://github.com/styled-components/styled-components"
target="_blank"
rel="noopener"
class = "sc-jDwBTQ "
>
GitHub
</a>
Currently styled-components uses MurmurHash algorithm to create a unique identifier and then converts the hash number to alphabetic name.
Each component instance with unique props has it’s own CSS class name which is generated by means of the MurmurHash algorithm, the componentId and the evaluatedStyles string:
const className = hash(componentId + evaluatedStyles);
Then this class name is stored in the component state as generatedClassName.
This was about all I could find in the styled-components FAQ
Each node actually has two classes connected to it: one is static per
component, meaning each element of a styled component has this class.
It hasn't any style attached to it. Instead, it's used to quickly
identify which styled component a DOM objects belongs to or to make
minor changes in the DevTools. It's also used for component selectors.
The static class probably will look something like: .sc-fVOeaW.
The other is dynamic, meaning it will be different for every element
of your styled component with different props, based on what the
interpolations result in. It will probably look like .fVOeaW (note the
lack of "sc" prefix.)
For example, the styled component <Button /> would render with the
same static class every time. If the styles are changed using
interpolations, like <Button secondary />, then the dynamic class will
be a different one, while the static class would remain the same.
Also, Motivation
No class name bugs: styled-components generates unique class names for your styles. You never have to worry about duplication, overlap or misspellings.
TL;DR They are automagically generated and maintained by styled-components.
Are you using Material UI for reactjs by any chance? If so,then just check in the package.json about the version details. If it's version has "rc" appended to it, then please update it to the previous/next stable version.
Related
I am using a dropdown from react-bootstrap and its context-menu has a className called Select-menu-outer. I wanted to change the font size of this menu only in one component.
What I did was, I just created a new css file called panel.css and did import './panel.css; in my component.
In the panel.css, I applied the style to the Select-menu-outer like
.Select-menu-outer { font-size: 12px }
This worked fine, but it affected the font size of all other dropdowns in the entire app.
I would have used CSS Modules and do something like import style from './panel.css and do className={style.Select-menu-outer} something like that, but since this is a third-party library component, I wasn't sure if I can do that.
Any good way to make this work?
Add a new class list to the drop down you what to change called .Select-menu-outer-size
Then do this in your css:
.Select-menu-outer-size { font-size: 12px !important}
The !important overrides the other class.
Javascript could be used!
let's say that it is the 3rd dropdown on that page with this class: .Select-menu-outer
So we do:
var addclass = document.getElementsByClassName("Select-menu-outer").[2];
addclass.classList.add("Select-menu-outer-size");
Then add you css:
.Select-menu-outer-size { font-size: 12px !important}
Note: 0 is 1 and 1 is 2 etc. for document.getElementsByClassName("Select-menu-outer").[2];
Linkhttps://www.w3schools.com/jsref/tryit.aspfilename=tryjsref_document_getelementsbyclassname
You can use the bsPrefix prop to customize the class of your component, in order to style it via CSS.
Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css.
Source: React-Bootstrap docs
You can use inline-styles on that specific menu to override the default style.
OR
you can assign an id e.g. id="outer-menu" to that specific menu tag and access that menu with #outer-menu in CSS.
The priority of id is greater than className so it will probably override it.
In this React Component I have Cookbook.js and Cookbook.css. I have a bunch of styles in Cookbook.css and specifically it has
form {
display: inline-block !important;
padding-top: 30px;
margin-left: 100px;
}
Which is fine since I import that into the Cookbook.js. But I created another Component called Survey.js along with Survey.css. In Survey.js I use a form as well but I ONLY import survey.css. Yet for some reason, The CSS from Cookbook.css gets applied to the form in my Survey.js. As a result, my form on Survey.js is in a odd spot. How Can I ensure that the css for each form is independent of each other?
When you create CSS rules, it is often easier to use class names instead of id's. Such as:
.class {
background-color: blue;
}
When you have common elements across multiple components, the CSS color will apply the styling to all elements such as:
p {
background-color: blue;
}
If you want to differentiate the styling where it applies in one component but does not apply to another which I think you are trying to do in your case, you need to use id's instead of element or class names.
Add an id to the component that you want to style and create a rule for that element such as:
#hero {
background-color: bluel;
}
This should be able to ensure that CSS is different from each other.
I think that you are looking for CSS modules. CSS modules are CSS files that only apply to a single component. Here is an example: https://css-tricks.com/css-modules-part-1-need/. More about CSS modules can also be found on Google and other forums.
Thank you,
Caiden Sanders.
In React when a component is mounted, its specific CSS file is also imported. You should know that React makes only a single HTML page application. In one HTML page if you import multiple CSS files and if they have conflicting CSS, then CSS will be applied on the basis of priority.
CSS that comes last overrides existing if common elements conflicting unless you haven't used !important with any property.
So, you should use unique ids or classes to prevent conflicts wherever required, and use common CSS if you have similar behaviour for certain elements.
In styled-components docs, they have this example:
https://www.styled-components.com/docs/advanced#referring-to-other-components
It shows an Icon that changes color when you hover its parent, which is a link, in this case.
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & { // <---- This is what I'm not understanding
fill: rebeccapurple;
}
`;
From the Docs, we know that:
Doc Note #1: styled-components solves this use case cleanly via the "component
selector" pattern. Whenever a component is created or wrapped by the
styled() factory function, it is also assigned a stable CSS class for
use in targeting.
And also that:
Doc Note #2: Ampersands (&) get replaced by our generated, unique classname for
that styled component, making it easy to have complex logic.
Let's analyze ${Link}:hover &
I know it gets translated into the browser as:
and:
I understand that sc-kAzzGY is the "stable CSS class" (Doc Note #1) that is created whenever an element is wrapped by the styled function.
I also know that the Ampersand (&) gets replaced by their generated unique classname (Doc Note #2) for that styled components. Hence, kDmLky is that class.
QUESTION
But what does the resulting selector (picture below) is actually selecting? Can anybody explain that to me?
${Link} is pointing to const Link i.e.: "Hovering my parent changes my style" which gets a class of sc-kAzzGY.
& is kinda like saying "And add this to the current class(es)/id(s)/etc."
So,
.my-class {
some-css: awesomeness;
&:hover {
more-css: extra-cool;
}
}
is equivalent to:
.my-class {
some-css: awesomeness;
}
.my-class:hover {
more-css: extra-cool;
}
Therefore, & points to the containing element const Icon i.e. the speech bubble and gets a class of kDmLky.
When Link is hovered, cause Icon to have fill: rebeccapurple
EDIT:
Just to clarify things a bit more:
When you have a declaration block inside of another declaration block like the example below, that inner declaration block becomes an independent one.
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & { // This declaraition block becomes an independent one
fill: rebeccapurple;
}
`;
And the result, in this case, is a declaration block with a selection that says:
When you have a class & which is descendent of the class ${Link} which is in the hover state, apply these rules:
fill: rebeccapurple;
NOTE: ${Link} refers to the Link class and & refers to the Icon class (svg).
${Link}:hover &
Here the ampersand & is the short hand way for referring to the top level component being defined, so I would read it as
${Link}:hover ${Icon}
i.e. it is referring to an Icon component contained inside of a Link component being hovered over
I would also recommend this link to see the more general use case for component selectors with styled components, where it's used in a parent child configuration for selection, and applied to the child
Im currently working on a Angular2 application with webpack and Im trying to set differents css themes according to the user.
For example : When the user connect, If it's a boy, I want to have my backgrounds blue, and if it's a girl I want the backgrounds to be pink.
Simply changing the css value with setAttribute or style.property wont work because the DOM is destroyed when changing tab in the application, it needs to be kinda permanent.
I've tried using different css stylesheets (1 for each theme) and linking them to my html with javascript when the user connect. Problem is, webpack is always adding automatically my css to my html when building the app.
Thanks for the help.
In your css, make a rule like :
.is-boy{
background: blue;
}
.is-girl{
background: pink;
}
and declare in you angular app a scope var like $scope.userSex = 'boy';
and on your body use ngClass like this
<body [ngClass]="{'is-boy': userSex === 'boy', 'is-girl': userSex === 'girl'}" ...
:host-context selector
You could use the :host-context selector to apply styles to your component based on the parent component.
styles:[`
:host-context(.parent1) div{
border: 1px solid blue;
}
:host-context(.parent2) div{
border: 1px solid blue;
}
`]
This allows you to conditionally apply styles based on a the selector that wraps the component.
plunker
edit:
So in your case - your parent would have a div with class .boy and a div with class .girl
You could load these containing divs with some flag controlled by ngIf
If you want to be permanent store class value in localStorage. To set the theme use ngClass with variable set to theme you need.
I just included a new js calendar in my project. The calendar displays like this -
<div style="position: absolute;" id="container">
<table cellspacing="0" cellpadding="0" align="center" class="DynarchCalendar-topCont">
<tbody>
<tr><td>
// lots of elements inside
<td><tr>
</tbody>
</table></div>
The problem is that the view of the calendar is appearing distorted due to some styles in my project like this -
div#sel_filters div.fields div {
margin-left: 10px;
}
div.filters div.fields div {
float: left;
padding: 7px 0 0;
}
... and many more which apply to the elements inside
There are many css files of the project. Since my calendar appears inside div.fields, the above styles apply to it as well. I am not considering altering the above project styles , as they may affect others.
What is the proper clean way of not allowing any styles other than those in the jscalendar.css file to affect it. DO I only have this option of applying !important to the styles in the jscalendar.css, and searching all the extra attributes, which are only set by project css, and setting them 0 or null manually.
In case it matters, I am free to include the jscalendar.css before/after project css files.
If you load your jscalendar.css after the other CSS files it should overwrite the other CSS directives.
If you still have problems, you could add a class to the divs that should behave differently and then add a CSS directive after the others to overwrite the previous ones:
div.filters div.fields div.yourClass {
float: none;
padding: 0;
margin: 0;
}
The proper way to do this unfortunately is to fix your site's CSS. What you're doing by applying styles to elements directly such as div's is going to lead to a world of pain for future maintenance or changes.
Avoid styling elements directly at all costs, use classes as much as possible, then IDs. Use elements with classes or IDs like div.foo or div#foo but not elements directly.
You could get away with !important in your calendar CSS for now but I'd spend that time fixing your site's CSS, as if ever you upgrade the calendar plugin you're looking at painful times again.
So take the hit now, look at the positive of having learnt how to do things properly and never repeat the same mistake again :)
apply a unique id to the container and change your CSS to reflect the heritage that derives from that... direct styling will get you to where you wanna go, but its gonna cost you in the long run if you have to maintain this later down the road...
but i must agree with Moin Zaman, if you hit this obstacle, its bound to happen again if you dont take care of it right now