I'm working on a project in which a user can select colors from a color input and create their own theme dynamically using CSS variables. I'd like the user to be able to download the entire CSS file with the values they selected.
My issue: The CSS file downloaded doesn't display the actual color values, but shows the variable name.
NOT WANTED
pre[class*="language-"] {
background: var(--block-background);
}
instead of
WANTED OUTPUT
pre[class*="language-"] {
background: #0D2831;
}
I know I can get CSS property values by doing the following.
const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue('--block-background')).trim()
I figured that I would create a function that loops through all my CSS variables and grabs the corresponding property values and then adds them to a new stylesheet for the user to download, but I got lost along the way. I currently have two CSS files, a main.css and a prism.css. The main.css file holds the page styling and all CSS variables within the root. The prism.css file contains the theme in which I want the user to be able to download.
I'm trying to find a way to create a new stylesheet that contains everything within the prism.css file but has the actual color hex code instead of the CSS variable name as a value to the given CSS property.
Index.js
import { colors } from './colorHelper'
const inputs = [].slice.call(document.querySelectorAll('input[type="color"]'));
const handleThemeUpdate = (colors) => {
const root = document.querySelector(':root');
const keys = Object.keys(colors);
keys.forEach(key => {
root.style.setProperty(key, colors[key]);
});
}
inputs.forEach((input) => {
input.addEventListener('change', (e) => {
e.preventDefault()
const cssPropName = `--${e.target.id}`;
document.styleSheets[2].cssRules[3].style.setProperty(cssPropName, e.target.value)
handleThemeUpdate({
[cssPropName]: e.target.value
});
console.log(`${cssPropName} is now ${e.target.value}`)
});
});
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
// Finds css variable names
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables).join()
console.log(cssVariables)
}
colorHelper.js
const colorSelect = {
'Line Highlights': {
'highlight-background': '#F7EBC6',
'highlight-accent': '#F7D87C'
},
'Inline Code': {
'inline-code-color': '#DB4C69',
'inline-code-background': '#F9F2F4'
},
'Code Blocks': {
'block-background': '#0D2831',
'base-color': '#5C6E74',
'selected-color': '#b3d4fc'
},
'Tokens': {
'comment-color': '#93A1A1',
'punctuation-color': '#999999',
'property-color': '#990055',
'selector-color': '#669900',
'operator-color': '#a67f59',
'operator-background': '#FFFFFF',
'variable-color': '#ee9900',
'function-color': '#DD4A68',
'keyword-color': '#0077aa'
}
}
const colorNames = []
const colors = {}
Object.keys(colorSelect).map(key => {
const group = colorSelect[key]
Object.keys(group).map(color => {
colorNames.push(color)
colors[color] = group[color]
})
})
export { colorSelect, colorNames, colors }
EDIT
I attempted to loop through the stylesheet and grab the CSS variable names, but some of them returned as an empty string.
This is what I did
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables)
console.log(cssVariables)
}
This was the result in the console
var(--base-color)
var(--selected-color)
<empty string>
var(--block-background)
var(--inline-code-color)
<empty string>
var(--comment-color)
var(--punctuation-color)
var(--property-color)
var(--selector-color)
var(--operator-color)
var(--keyword-color)
var(--function-color)
var(--variable-color)
<empty string>
var(--highlight-background)
I then attempted to chain .replace() after the trim() but that didn't seem to work either.
from How to generate CSS variable values to a new stylesheet
No comments:
Post a Comment