Dynamically Changing an Injected CSS Class ...Good? ...Bad?
I found a 'need' to modify a CSS Class that I inject into the header vis javascript. Because I build the class dynamically and inject it into the header, I found it easy to modify the Class's text and put it back into the CSS Class definition whereby changing it.
By inject, I mean:
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = ".classname { ...css text... }";
document.getElementsByTagName('head')[0].appendChild(style);
and by modifying the Class, I mean simply changing the text:
{ ...css text... }
and putting it back:
style.innerHTML = ".classname { ...new css text... }";
I really have not seen this done before and am asking if there is a reason that this is not done more often? ...that is, "is this a bad practice?" and perhaps "are there browser/device combinations where this may not work?"
Thank you.
This is a bad practice. A CSS class should have a single definition. Modifying the class conditionally makes your code hard to follow and hard to maintain.
The correct way would to be create a separate CSS class for each condition, or modify the DOM directly using Javascript.
Related
I am using webpack to generate a single bundle.js file containing everything I need in a single file, and the webpack compiles and seems to contain what I expect. I am dynamically generating DOM elements in javascript that I would like to be formatted with existing sass class specifications as follows:
index.scss:
.classname {
position: 'absolute';
font-family: 'Roboto', sans-serif;
color: blue;
}
index.js:
import styles from './css/index.scss';
console.log(styles);
let aDiv = document.createElement("div");
aDiv.classList.add("classname");
aDiv.style.top = "10px";
document.body.append(aDiv);
let bDiv = document.createElement("div");
bDiv.classList.add(styles.classname);
aDiv.style.top = "30px";
document.body.append(bDiv);
In Firefox's developer tools, from the console, I can see that styles is an object with a property for each of many css rules, one of which is:
"classname": "_2mpyBRPOMJ9D3LKNxOIvrs"
In Firefox's Inspector tool, aDiv's class is "classname", but no styles are applied from that class. bDiv's class is "undefined", and no styles are applied there either. I cannot figure out how to get the "_2mpyBRPOMJ9D3LKNxOIvrs" class name, which is different each time I compile, assigned as a class. But even when I do this manually from Firefox, the styles are never applied, and neither "classname" or "_2mpyBRPOMJ9D3LKNxOIvrs" exist in Firefox's style editor.
Is it possible to dynamically create an element that inherits styles from scss via its class name? Or is there a nicer cleaner way to do this that I'm missing? I feel I must have failed to grasp a central tenet of webpacking css into js.
This is because the minification plugin changes your class names to new references when your scss gets merged as css into your code. You can disable this behavior by configuring webpack. Thia answer tells you how to do it:
How to disable webpack minification for classes names
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.
I have inline css in my element which i do not want. There is a lot of js in my website and i do not know from where this css is coming.
Any help will be great.
Thanks in advance.
If I were you, I'd use removeAtrr() to remove all the inline style for that element:
$('#yourElementId').removeAttr("style");
After that, I'll set any style again through external css file or javascript if necessary.
Or if you want to override the inline styles, you can also try to use !important attribute in css.
I think the most solid way to do it would be to use the browser's dev tools to run through the js one line at a time. This will show you the exact point in the code execution where the style is added. Here's a link demonstrating how to use breakpoints: https://developers.google.com/chrome-developer-tools/docs/javascript-debugging#breakpoints
Otherwise, if you're confident the code will be jQuery functions, do a search for .css(. If it's possible the change is made without jQuery, search for .style.. Some other possibilities are fadeIn, fadeOut, and animate. Once you find any of these, you can track what element they are being applied to to determine if they are relevant to the element you want to change.
Here are some selectors to look out for (vanilla JS and jQuery)
ClassName
document.getElementsByClassName('some-class');
$('.some-class');
ID
document.getElementById('some-id');
$('#some-id');
TagName
document.getElementsByTagName('tagNameHere');
$('tagNameHere');
QuerySelector
document.querySelector('cssSelectorHere');
document.querySelectorAll('cssSelectorHere');
$('cssSelectorHere');
If the problematic CSS is set with jQuery, you can hook into jQuery's cssHooks API to see when a particular CSS is being set. For example, if the problematic CSS is "margin-right" you can detect when it is being set and throw an exception so you can trace it through the browser's debugger:
var targetElement = document.getElement("checkme");
$(function() {
$.cssHooks["marginRight"] = {
set: function(node, value) {
if(node == targetElement) {
throw "stop that!";
}
else node.style.marginRight = value;
}
};
});
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>');
});
});
Does anyone know how i can make my textarea in a ckeditor object, use a class or custom style so i can show to the user something similar to what is getting rendered in the site?
Thanx
So i'm using bodyClass: 'class' in the config object, i use firebug and see the iframe body has my class applied, but it doesn't get the classes properties neither from my CSS, nor from contents.css (ckeditor)...
Well i was able to do it, adding an event to the object like this:
editor.on('instanceReady', function(){
$('#'+divname).find('iframe:first').contents().find('body').css({
'background-color':'#000000',
'font-family':'arial',
'font-size':'12pt',
'color':'#cdcdcd'
});
});
if anyone has the real solution, i think bodyClass should be it, i will gladly change my code.
Thanx
Simply edit the css file located at contents.css - edit the .cke_editable class to whatever suits your needs. Works 24/7