The setup below works as expected on:
yarn serve
However it does not add the custom theme varaiables to the generated CSS file on:
yarn build
Setup:
project\src\assets\tailwind.css
#tailwind base;
#tailwind components;
#tailwind utilities;
#layer components { [...] }
#layer base {
:root{
--color-text-title: 0, 0, 0;
[...]
}
.theme-customOne{
--color-text-title: 0, 255, 0;
[...]
}
.theme-customTwo{
--color-text-title: 0, 0, 255;
[...]
}
}
project\tailwind.config.js
function withOpacity(variableName) {
[...]
}
module.exports = {
purge: { content: ["./public/**/*.html", "./src/**/*.vue"] },
darkMode: false,
theme: {
extend: {
textColor: {
skin: {
title: withOpacity("--color-text-title"),
[...]
}
}
}
}
}
Output:
project\dist\css\index.cae56bc4.css
:root{
--color-text-title: 0, 0, 0;
[...]
}
Is there a way to get the theme specific CSS Variables in the generated CSS file as part of the build process?
I figurd it out by myself.
The solution is to add the custom classes you would like to preserve to your tailwind.config.js like so:
module.exports = {
purge: {
content: ["./public/**/*.html", "./src/**/*.vue"],
safelist: ["theme-customeOne", "theme-customTwo"]
},
[...]
}
After that you can run:
yarn build
If you now check the generated CSS e.g. project\dist\css\index.cae56bc4.css
you will find the custom class + custom CSS variables inside that file.
I share my solution in case it might be helpful to anyone else who will come across
this issue.
Related
I'm having an issue converting my postcss conditionals to css. I'm using vite to process the files and output a css file. Everything seems to be working up until the point that I try to convert the conditionals (see below).
Here is my vite file:
import { defineConfig } from 'vite';
import postcss from './postcss.config.js';
import dns from 'dns';
dns.setDefaultResultOrder('verbatim');
export default defineConfig({
root: 'src',
build: {
manifest: 'vite-manifest.json',
rollupOptions: {
input: {
main: './src/scripts/main.js',
},
},
outDir: '../dist',
emptyOutDir: true,
},
css: {
postcss,
devSourcemap: true,
},
server: {
hmr: {
protocol: 'ws',
},
},
});
Here is a simplified version of my postcss file:
import atImport from 'postcss-import';
import atMixins from 'postcss-mixins';
import atIf from 'postcss-conditionals';
import nested from 'postcss-nested';
export default {
plugins: [
atImport,
atMixins,
atIf,
nested,
],
};
The mixin I'm trying to parse:
#define-mixin center-x $position, $distance {
position: absolute;
left: 50%;
transform: translateX(-50%);
#if $position == top {
top: $distance;
bottom: auto;
} #else {
top: auto;
bottom: $distance;
}
}
This gives me this error: [vite:css] postcss-conditionals: src\styles\base\mixins.css:6:5: Failed to parse expression file: src/styles/main.css error during build: CssSyntaxError: postcss-conditionals: src\styles\base\mixins.css:10:5: Failed to parse expression
Furthermore replacing the if else inside the mixin with:
#if 3 < 5 {
background: green;
}
doesn't give me that error.
Maybe the mixin variables aren't resolved yet before the conditionals can use them but I don't know how to get those resolved first. Really hope someone knows how to fix this.
Gave this another try today, still can't fix it so I replaced the following plugins:
postcss-for
postcss-each
postcss-each-variables
postcss-mixins
postcss-conditionals
for postcss-advanced-variables where combining conditionals and mixins works out of the box, the downside is that I have to use SASS syntax instead of postcss syntax but that's ok I guess.
I have several custom utilities configured in my tailwind.config.cjs file this:
plugins: [
plugin(({ addUtilities }) => {
const utilities = {
'.border-invalid': {
border: '1px solid #ef4444',
},
[...]
};
addUtilities(utilities);
}),
],
I also have defined custom colors, like this
extend: {
colors: {
'red-50': '#FEF2F2',
[...]
'red-500': '#EF4444',
[...]
}
}
Instead of having the hard-coded value in my custom utility, I'd like to reference my custom color, so that if I ever change my color palette my custom utilities would be updated accordingly. So, ideally, it would be something like this:
const utilities = {
'.border-invalid': {
apply: 'border border-solid border-red-500',
},
Or some way to reference red-500 in my custom utility instead of the hard-coded #EF4444.
Is there a way to achieve it?
#ihar-aliakseyenka answer workes great, I added this just to tell that the second alternative, border: "1px solid theme('colors.red-500')" even show a nice and clear css definition when flying with the mouse over:
While the first option, border: 1px solid ${theme('colors.red-500')}` just show the literarl value (as expected, btw):
You may use theme() directive
plugins: [
plugin(({ addUtilities, theme }) => { // extract theme
const utilities = {
'.border-invalid': {
border: `1px solid ${theme('colors.red-500')}`, // concatenate
}
};
addUtilities(utilities);
}),
],
// or pass it as a string
plugins: [
plugin(({ addUtilities }) => {
const utilities = {
'.border-invalid': {
border: "1px solid theme('colors.red-500')",
}
};
addUtilities(utilities);
}),
],
Note: you set your color as red-500, so no dot notation will be available like theme('colors.red.500') (it will cause error. Well maybe not because Tailwind has red-500 color but in any other cases it will)
DEMO
I am looking to extend the margin style and add the variant ['even'] to it.
I can add the variant like so:
module.exports = {
variants: {
margin: ['even'],
},
theme: {
...
}
}
It is my understanding that the above will override the margin styles default variants.
The documentation here shows the ability to extend a variant as to not remove all the defaults when adding the new variant (discussed more here).
I have tried this and not been successful:
module.exports = {
variants: {
extend: {
margin: ['even'],
},
},
theme: {
...
}
}
I must be doing something wrong or have a typo?
The reason I was unable to do this was because of my tailwindcss version being below 2.0. As #Jon suggested. Thanks! 2.0 release notes.
I'm trying to allow my users to have different themes to choose from however I can't seem to get it working. I've tried multiple different ways, one way is having two different files and i import them based on if the theme is light/dark however once it's imported it stays on the page. Another is within SCSS like this:
$enable-rounded: true;
[theme="dark"] {
$blue: #232c3b;
$body-bg: #262626;
$body-color: white;
}
[theme="light"] {
$body-bg: #ffffff;
$body-color: #000000;
}
#import 'bootstrap/scss/bootstrap.scss';
#import 'bootstrap-vue/src/index.scss';
then in my layouts/default.vue:
import(`~/assets/scss/main.scss`)
export default {
data() {
return {
darkMode: false,
}
},
mounted() {
let bodyElement = document.body;
bodyElement.classList.add("app-background");
let htmlElement = document.documentElement;
let theme = localStorage.getItem("theme");
if (theme === 'dark') {
bodyElement.setAttribute('theme', 'dark')
this.darkMode = true
} else {
bodyElement.setAttribute('theme', 'light');
this.darkMode = false
}
},
watch: {
darkMode: function () {
let htmlElement = document.documentElement;
if (this.darkMode) {
localStorage.setItem("theme", 'dark');
htmlElement.setAttribute('theme', 'dark');
} else {
localStorage.setItem("theme", 'light');
htmlElement.setAttribute('theme', 'light');
}
}
}
}
however nothing happens when I do it this way. I've been trying to figure it out for days and can't seem to get it. It makes me want to just use CSS and avoid SCSS even though I really want to use scss
I think you are importing your scss file in a wrong way. Please try importing it like below out of the script part:
<style lang="scss">
#import '~/assets/scss/main.scss';
</style>
I think you can use this for your project, you can switch into themes or custom on your own
https://color-mode.nuxtjs.org/
chrome.tabs.insertCSS(tabId, { code : '#import url("custom.css");' });
OR
chrome.tabs.insertCSS(tabId, { file : 'importer.css' });
importer.css:
#import url("custom.css");
a { color:red!important; } /* this rule applied successfully though. */
Doesn't seem to work as expected.
Why doesn't it work and how to make it work?
Edit:
Maybe I am looking at the wrong source code location, but the source code indicates that it uses the regular style sheet parser to parse the injected CSS. In other words, if the #import directive works in regular CSS documents, it should also work in injected CSS.
https://code.google.com/p/chromium/codesearch#chromium/src/extensions/renderer/script_injection.cc&q=script_injection.cc&sq=package:chromium&type=cs&l=312-320
void ScriptInjection::InjectCss(blink::WebLocalFrame* frame) {
std::vector<std::string> css_sources =
injector_->GetCssSources(run_location_);
for (std::vector<std::string>::const_iterator iter = css_sources.begin();
iter != css_sources.end();
++iter) {
frame->document().insertStyleSheet(blink::WebString::fromUTF8(*iter));
}
}
Edit:
Sample code that's not working:
Directory structure:
ext.root
|-- custom.css
|-- custom.css.js
|-- importer.css
|-- manifest.json
manifest.json:
{
"background": {
"scripts": [ "custom.css.js" ],
"persistent": true
},
"manifest_version": 2,
"name": "custom.css",
"version": "1.0",
"web_accessible_resources" : [ "*" ],
"permissions" : [ "webNavigation", "http://*/", "https://*/" ]
}
custom.css.js:
chrome.webNavigation.onCommitted.addListener(function(details) {
console.log('inserting css');
console.log(chrome.runtime.getURL("custom.css"));
chrome.tabs.insertCSS(details.tabId, { file : 'importer.css' });
chrome.tabs.insertCSS(details.tabId, { code : '#import url("custom.css");' });
chrome.tabs.insertCSS(details.tabId, { code : '#import url(custom.css);' });
chrome.tabs.insertCSS(details.tabId, { code : '#import url("' + chrome.runtime.getURL("custom.css") + '");' });
chrome.tabs.insertCSS(details.tabId, { code : '#import url(' + chrome.runtime.getURL("custom.css") + ');' });
chrome.tabs.insertCSS(details.tabId, { code : '#import "custom.css";' });
chrome.tabs.insertCSS(details.tabId, { code : '#import custom.css;' });
chrome.tabs.insertCSS(details.tabId, { code : '#import "' + chrome.runtime.getURL("custom.css") + '";' });
chrome.tabs.insertCSS(details.tabId, { code : '#import ' + chrome.runtime.getURL("custom.css") + ';' });
});
importer.css:
#import "custom.css";
#import "chrome-extension://__MSG_##extension_id__/custom.css";
#import custom.css;
#import chrome-extension://__MSG_##extension_id__/custom.css;
#import url("custom.css");
#import url("chrome-extension://__MSG_##extension_id__/custom.css");
#import url(custom.css);
#import url(chrome-extension://__MSG_##extension_id__/custom.css);
body { background-color: red!important; } /* change page background color to red */
custom.css (Rules in this file are supposed to be applied but not):
body { border: 20px solid red!important; } /* add a 20px border around the body. */
a { background-color: blue!important; } /* change all link's background color to blue. */
If you try to inject such a file into a tab, relative URLs take its origin.
I.e. if you try to inject this into http://example.com/test/index.html, then the above CSS will try to load http://example.com/test/custom.css.
If custom.css is packed in the extension, you should use absolute path obtained from chrome.runtime.getURL():
chrome.tabs.insertCSS(
tabId,
{ code : '#import url("' + chrome.runtime.getURL(custom.css) + '");' }
);
You may try to use the special constant ##extension_id:
#import url("chrome-extension://__MSG_##extension_id__/custom.css");
but I'm not 100% sure it'll work.
Lastly, make sure the imported CSS file is in web_accessible_resources.
#important doesn't work with tabs.insertCSS(). insertCSS seem to be interpreted before injection in the page. How they are interpreted is not documented. For example !important do not works neither.