What happens when i use inline style and css files in React? - javascript

I am refering to a situation in which i have something like this:
import "./myCss.css"
const BeautyButton = (props) =>{
return (
<a style={{backgroundColor:"red"}} className="blue-background" >hello</a>
);
}
Which property prevails? Is there a general rule for all the properties (fontSize, width, etc)?

There is nothing different between how CSS works in React and with regular HTML. To understand which rules take effect, you'll want to study the concept of Specificity in CSS.
For your specific question, inline styles are considered more specific than styles in external stylesheets, so those styles will prevail.

Related

Load essential styles to shadow-dom

I love the idea of shadow dom styles encapsulation, but I'd like to include base styles to each shadow dom (reset, typography, etc).
<head>
<link rel="stylesheet" href="core.css">
...
</head>
<my-component></my-component>
<script>
customElements.define('my-component', class MyComponent extends HTMLElement {
...
connectedCallback() {
this.shadow = this.attachShadow({mode: 'open'});
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'core.css');
// applying exiting "core.css" to current shadow dom
this.shadow.appendChild(linkElem);
}
});
</script>
Since core.css was called (linked) twice will it affect the performance?
You could try use Constructable Stylesheet Objects
With this approach you can define global styles and then use them with shadowRoot.adoptedStylesheets like the following:
import {
resetSheet,
headlinesSheet,
coreSheet,
} from '/style-system.js';
import {
myComponentStyles,
} from './styles.js';
// ...
connectedCallback() {
// Only compose styles once
if (!this.shadowRoot.adoptedStyleSheets.length) {
this.shadowRoot.adoptedStyleSheet = [
// global stylesheets
resetSheet,
headlinesSheet,
coreSheet,
// specific sheet for this component
myComponentStyles
]
}
}
The main advantages with this approach in comparison with the one you're using (creating link elements to each component) are:
You can share global styles to be used across multiple components defining them once
You only load the styles being used by that component being rendered and this scales performance because it lazily loads stylesheets
You can change those global styles dynamically (as they're a JS component) without the need of applying changes in multiple elements, making more decoupled changes
As this is a quite new approach, I'd recommend you read the following articles in order to create a more solid knowledge about Constructable Stylesheet Objects
Constructible Stylesheets
Why Would Anyone Use Constructible Stylesheets, Anyways?
Adopt a Design System inside your Web Components with Constructable Stylesheets
The browser will cache the request for core.css so there's not really a performance penalty, but since the stylesheet will be loaded asynchronously you might get a flash of unstyled content (FOUC) while the browser fetches the css for the first time.
One possible way to get around this is to preload the css file in your document <head>, so that it will (probably, as preloads are only 'hints' to the browser) be available by the time your Shadow DOM is parsed:
<link rel="preload" href="core.css" as="style">

styling google-map-react map

I am building a map with google-map-react and trying to style it with no luck. I am using the documentation here: https://github.com/google-map-react/google-map-react/blob/master/API.md and adding styles via a prop called options like it says but I am not seeing any styles being applied.
Here is my code:
const createMapOptions = () => {
return {
styles: [{stylers: [{'saturation': -100}, {'gamma': 0.2}, {'lightness': 4}, {'visibility': 'on'}]}]
}
}
const Map = ({center, children, onGoogleApiLoaded, useGoogleMapsApis, zoom}) => {
return (
<div className='h-100p w-100p'>
<GoogleMap
bootstrapURLKeys={{key: '...'}}
defaultCenter={center}
defaultZoom={zoom}
options={createMapOptions}
yesIWantToUseGoogleMapApiInternals={useGoogleMapsApis}
onGoogleApiLoaded={onGoogleApiLoaded}
>
{children}
</GoogleMap>
</div>
)
}
Any guidance on how to get ANY styling applied would be greatly appreciated.
Note - I am using a developer key, not sure if that could be why I am not seeing the styling?
Also Note - I do not want tips on react-google-maps a similar library, but not the same as google-map-react. Ive seen other google-map-react questions answered and up voted with people referring to react-google-maps.
Some times styling in react as difficult when you use packages. So the Best Way to do it is
Open Inspect Element in your browser
Select the Particular Element whose styling you want to modify.
Copy the class that is used in it already.
Make changes to the same css className in your own scss or css file and will modify.
Note : If nothing Happens Try using the !important in the property.
https://developers.google.com/maps/documentation/javascript/controls#ControlOptions
Use this as resource to change css for the package.
Screenshot from the the above resource

Apply multiple styles with .style() method in D3.js

As I'm making my first steps into d3.js I couldn't help myself noticing its approach is very similar to jQuery.
My question is:
When I need to modify multiple CSS properties of a style attribute
of matching element is there a shorthand approach, like jQuery or
ReactJS provide, like
.style({width:100, height:100, backgroundColor:'lightgreen'})`
if I need to apply width:100px, height:100px and
background-color:lightgreen to a <div>.
Sure, I may chain those, but changing multiple properties this way may become tedious:
d3
.select('#test')
.style('width','100px')
.style('height','100px')
.style('background-color','lightgreen')
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script><div id="test"></div>
Or I may combine multiple desired properties within a class and assign that class with a .classed(), which may also overcomplicate CSS stylesheet when dynamic properties are required:
d3
.select('#test')
.classed('testclass', true)
.testclass {
height: 100px;
width: 100px;
background-color: lightgreen;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script><div id="test"></div>
But those are not techniques I'm interested in.
The accepted answer is not correct ("there's no such syntax documented in API reference"), you can set multiple styles using d3-selection-multi. Pay attention to the fact that you have to use the method styles(), not style(). So, in your case, it would be:
.styles({width:100, height:100, 'background-color':'lightgreen'})
Here is your snippet with that change:
d3.select('#test')
.styles({
'width': '100px',
'height': '100px',
'background-color': 'lightgreen'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="test"></div>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
As d3-selection-multiis not part of the default bundle, you'll have to reference it separately.
Edit (2021):
Note: I claimed (in initial version of this answer) that there's no embedded method to solve the OP's problem. And, as of D3 v6.7.0 you still cannot pass your styles as an object directly to .style() method
Two options you got by the time of this writing:
loop through your styles object and apply the styles incrementally
const style = {"width":"100px","height":"100px","background-color":"lightgreen"}
Object.entries(style).forEach(([prop,val]) => d3.select("#test").style(prop,val))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script><div id="test"></div>
use d3-selection-multi (solution massively upvoted down this thread)
Why I would discourage you from doing the latter:
the referenced repo is long time archived (since 2017), so it may raise all sorts of interoperability issues, which may possibly be the reason for its descending popularity
under the hood that library does exactly the same thing (looping and applying styles incrementally)
So, whether you apply 1-line solution or add up to 13kB of legacy code to your application bundle for that sole purpose - is totally up to you.
Alternatively, you can use the attr() method and add the styles as part of the attribute of that particular tag being targeted:
d3.select("#test")
.attr("style", "width: 100px; height: 100px; background-color: lightgreen;")
Unfortunately, there is not a better shorthand method for applying multiple styles to an element using Vanilla JavaScript. The ideal solution, in my opinion, is to apply a class to the element you wish to style that contains the multiple styles you wish to apply.
You could, of course, write a helper method that duplicates the JQuery method.
function applyStyle(id, styles){
Object.keys(styles).forEach(key => document.getElementById(id).setAttribute("style",key +": "+styles[key]+";"));
}
Since you can access d3 node by calling .node() on needed selection, you can do smth like that:
item.node().style.cssText = `property: value; property2: value2`;
Also, if you use styled-components (react), you can simply insert your css like this:
item.node().style.cssText = PreviouslyDefinedCSS.toString();
where css is smth like this:
import { css } from "styled-components";
const PreviouslyDefinedCSS = css`
your scss here
`;

Issue using multiple styles with Material-ui and Radium

I am trying to combine Radium and Material-ui. When I try to apply multiple styles on a single Material-ui component, no style is applied. So, for example, something like this produces no styling applied:
<MenuItem style={[styles.styleOne, styles.styleTwo]} >
Of course, if I do something like:
<MenuItem style={Object.assign({}, styles.styleOne, styles.styleTwo)} >
it works. Is there some way around it or this is the only way to use Radium for combining styles for a Material-ui component? And just to mention, Radium is properly set up, because applying array of styles on, for example, DIV element or works properly.
Also, I am open to any suggestion about styling a React project that uses Material-ui library. Thanks!
For material-ui components in react, we add styles using the className. If i have to add multiple styles in a material component then below are the methods:
Example 1:
<div className={`${style1} ${style2}`}>
Example 2:
import classNames from 'classnames';
<div className={classNames(classes.style1, classes.style2)} />
Specifically for your case (Radium):
What it's doing is merging 2 objects (style1 and style2) into a new anonymous object {} which is what you need to do.
You'll want to be careful when doing this however as you'll need to consider how you merge if both objects define the same key e.g. if style1 and style2 both define a height which do you use?
There's a long list of possible ways to do this on this stackoverflow thread http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically depending on the libraries you're using and your use case they each have their own pros and cons.
Instead of adding classnames, you can also use the clsx module that comes with Material UI and combine your style classes.
{/* using arrays */}
<MyComponent classes={clsx([classes.text, classes.title])} />
{/* using conditions */}
<div className={clsx(classes.root, {
[classes.base]: true,
[classes.closed]: !open,
[classes.open]: open
})]>
{props.children}
</div>
The Material UI Mini Variant Drawer example does a great job showing this module off.
Check out this fiddle: https://jsfiddle.net/Lxh5x2qr/
It uses the JSX spread (...) operator, which is a bit nicer syntax:
styleOne: {
background: 'blue',
color: 'red'
},
styleTwo: {
background: 'green'
},
... style={{...this.styleOne, ...this.styleTwo}} ...
Please notice the the order of object does matter, just like in Object.assign.
We should not forget that MenuItem is not a DOM element, so when we apply style to it, material-ui manipulates it before applying it to the underlying element, and probably this is the reason why using an array does not work.

How to include CSS for a specific part of the page

In my website, the users have to enter markdown in a textarea, for which I am using a markdown editor. The problem is: it uses icomoon font, and my websites too. Both uses the same class to define the fonts, but not both uses the same icons. The question is simple: is there a way to define the editor.css for a special div?
Like that:
<div css="editor.css"></div>
Give the DIV a Class and then add a CSS file like this:
.markdown
{
color: red;
}
If you import a new css dynamic, the old styles will be overwritten.
Some help, for dynamic css loading: How to apply inline and/or external CSS loaded dynamically with jQuery
Namespace your editor styles
You can add a selector that namespaces your editor and allows you to style it:
<div class="editor-style">
<div id="cool-custom-editor">...</div>
</div>
In your css:
.editor-style .icon-thumbs-up { color: green; }
Using Scoped Styles (needs polyfill)
As mentioned in #adeneo's comment below your question there is the option of using scoped style tags.
Supposing your editor looks like this:
<div id="cool-custom-editor">...</div>
You can apply a specific style using the scoped attribute like so:
<div>
<style scoped>#import url(editor.css);</style>
<div id="cool-custom-editor">...</div>
<div>
Caveats
According to can I use the scoped attribute is only natively supported by Firefox 26+.
If you want to use it you will have to polyfill:
Plain JavaScript polyfill
jQuery scoped plugin
Further Reading
HTML5 Doctor - The scoped attribute
CSSTricks - Saving the day with scoped styles
HTML5Rocks - A new experimental feature - Scoped Styles
You dont need multiple files. You can give the div an id or class like so
<div class="div1">
<span></span
...
</div>
and now in you css you do this
.div1 span{
font:(whatever font);
}
I don't think so, no. At least not without using any js workarounds. The best solution would be to use kind of namespace for user-specific css classes.
No you can't do that.. I think you should solve the conflit by changing the icomoon class names in this file.
OK solved: renaming the classes in editor for icomoon was a lot easier than I dared tough.
not a good way but it can help:
$("[css]").each(function(i){
var elm = $(this);
$.when($.get(elm.attr("css"))).done(function(response) {
var newresponse=response.replace(/(.+{)/gi,".customCss"+i+" $1");
elm.addClass("customCss"+i);
elm.before('<style>'+newresponse+'</style>');
});
});

Categories

Resources