Generating a class in javascript to match existing sass class name - javascript

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

Related

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

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.

JavaScript: (How) can one retrieve external CSS rules in Chrome's DevTools?

I'm working on a little Chrome extension that extends its DevTools. For this, I need to acquire all of the defined CSS selectors for the currently selected element ($0).
I know each item within document.styleSheets exposes all of the necessary data through cssRules. This would be perfect, but unfortunately CORS seems to throw a spanner in the works. For external stylesheets, cssRules returns null.
Is it possible to access this data without resorting to a hackish solution, e.g. downloading the stylesheet and inserting it into a style tag? I ask because Chrome itself seems to do so in its Styles sidebar panel, but I can't find much information on the matter.
Thanks!
I think I've figured it out. It just took a bit more digging in the documentation.
The inspectedWindow API exposes getResources, allowing you to fetch all of the resources within the inspected window. This includes type and functionality for fetching its content.
Injecting this content into a style tag allows you to access the CSS rules via document.styleSheets. This is ideal because my sidebar pane is encapsulated within a shadow DOM, allowing me to know exactly which stylesheets have been injected.
chrome.devtools.inspectedWindow.getResources(function(resources) {
for (var i = 0; i < resources.length; i++) {
if (resources[i].type != 'stylesheet') {
continue;
}
// inject the resource into the shadow DOM
// this allows us to freely access all CSS rules CORS-free
resources[i].getContent(function(content) {
var style = document.createElement('style');
style.textContent = content;
document.body.appendChild(style);
});
}
});

Can I use javascript to change individual page css entries (as opposed to swapping stylesheets)?

I know it's possible to change css attributes on elements on the current page:
$('.changeMyStyle').css("color", "#FF0000");
But this won't affect new elements added after the change is made.
I know it's possible to remove, add, or swap out css stylesheets to re-style a page after it's been loaded:
$('link.swappableStylesheet').attr('href', 'path/to/new/style.css');
But this is a poor solution for changing one or two attributes, especially to programmatically-determined values (such as changing color from a colorpicker).
I could probably grab a stylesheet's raw data, search it, and modify it:
var sheet= document.styleSheets[0];
var rules= 'cssRules' in sheet? sheet.cssRules : sheet.rules; // IE compatibility
rules[0].style.padding= '0.32em 2em';
// assumes the first entry in the first stylesheet is the one you want to modify.
// if it's not, you have to search to find the exact selector you're looking for
// and pray it's not in a slightly different order
But that's also a poor solution and requires IE-compatibility hacks.
This linked answer also suggests appending another <style> element and adding css there. That could work for narrow cases, but it's still not ideal (and the answer is 5 years old, so new tools may be available now).
Is there a way to alter the page's css at a selector & attribute level instead of stylesheet level or DOM element level? jQuery and vanilla javascript solutions both welcome, as well as libraries designed to do this specifically. Ideally I'd like something that's as easy and versatile as
$(document).stylesheet('.arbitraryCssSelector.Here').put('color', '#FF0000');
...where .stylesheet('.Here.arbitraryCssSelector') would modify the exact same style entry.
Even Chrome's dev tools just modifies the stylesheet it's using when you make modifications or add new rules. There's not currently a way around it, but you can keep a dedicated stylesheet at the bottom of the page that you update with the newest rules. If it's empty or contains invalid rules it will just fall back to the current stylesheet. If any library exists out there this is how it would do it, and it's very little code.
I think the key to keeping it uncluttered is to simply keep overwriting one stylesheet instead of adding new stylesheets to the DOM.
document.getElementById("dynamic-color").addEventListener("input", function () {
document.getElementById("dynamic-styles").innerHTML = "label { color: " + this.value + " }";
});
label {
color: blue;
}
<label for="#dynamic-color">Change the label's color!</label>
<input id="dynamic-color" />
<style id="dynamic-styles"></style>

Dynamically Changing an Injected CSS Class ...Good? ...Bad?

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.

Modulizing CSS Stylesheets with RequireJS

I have created a template like so:
// template.tpl
<div>
<input id="an_input"></input>
</div>
and some CSS:
// stylesheet.css
input {
background: #000000;
}
Finally this is a slimmed down module:
define([
'jquery',
'text!template.tpl',
'text!styleshet.css'
], function($, html, css){
var view = $('#sample_div');
view.append($(html));
var regex = /^([^\s\}])/gm;
var styles = css.replace(regex, '#'+view.attr('id')+' $1');
var style = $('<style>\n'+styles+'\n</style>');
view.prepend(style);
});
What is essentially happening, is the template is being loaded and put into the #sample_div. Shortly after the CSS file is being loaded as text, then every item is prefixed with the ID of the view.
Once the CSS is prefixed, the style tag is created and placed inside the view.
Now, this works perfectly, OK it isn't pretty, nor does it leave much margin for error. However I wrote this code to help demonstrate what I need.
I need to be able to load templates with view specific stylesheets, where the styles in the sheet will only ever apply to the view and will only override global styles.
The problem with the above example is that it is a hack, a regex against the CSS, and the building of a new style tag, this is not how I want to do it. I have been looking into javascript CSS parsers for a cleaner solution, and although JSCSSP caught my eye, it put to many functions into the global namespace, and jquery.parsecss only seems to work with styles already within the document.
Does anyone have any experience with what I am trying to achieve?
Most loaders out there have CSS plugins that handle the insertion for you:
RequireJS CSS plugin
https://github.com/tyt2y3/requirejs-css-plugin
CurlJS CSS plugin is bundled with the main distribution:
https://github.com/cujojs/curl/tree/master/dist

Categories

Resources