How to execute different sass files based on a css class? - html

I am wondering how can I can include a different sass file (theme) based on a certain class?
Now we got 3 apps which all have an unique css class for its styling (.app1 {.background-color: red;})
Now i want to include sass framework and seperate all the css/sass per app label. In order to achieve this we define a base.scss. In this scss we want to reach this:
if .app1 then execute app1.scss
else if .app2 then execute app2.scss
else if .app3 then executr app3.scss
else empty
Anyone an idea?

Use a namespace and apply it as a class to the root element. Wrap SASS statements in the appropriate namespaces. You can separate them into different files (partials) and combine them when they get compiled.
// in file _app1.scss
.app1 {
// rules you want applied in the "app1" case
}
// in file _app2.scss
.app2 {
// rules you want applied in the "app2" case
}
...
If you separate files into _app1.scss, _app2.scss, etc. then base.scss will include:
#import 'app1';
#import 'app2';
...
This combines the partial files into one when you compile. (You don't have to separate them, but it might be cleaner to do so.) Then, you do something like <body class="app1">... to use the app1 namespace, and only rules from _app1.scss will apply.

Related

CSS #import with URL / Path specified as a custom property (variable)

I was thinking about a convenient way to create and use themes in HTML / CSS / JS. One possible solution I was thinking of was specifying the path to the theme file as a variable and importing the theme file in the main stylesheet via said variable so something along these lines:
:root {
--theme: url("default-theme.css");
}
#import var(--theme);
This way, if later the theme needs to be changed (for instance for Halloween or for the holiday season etc), the theme can be updated by either manually updating the value of the CSS variable or by using JS / TS to programmatically update the value.
I have tried a couple of different iterations of this including:
:root {
--theme: "default-theme.css";
}
#import var(--theme);
and
:root {
--theme: "default-theme.css";
}
#import url(var(--theme));
But sadly, nothing seems to work. I have also read through the documentation for CSS custom properties and CSS import and so far I have not really found anything.
Here is some editable sample code on StackBlitz. If anyone has any advice or suggestions or some wisdom to share, I will be extremely appreciative.

purgecss can't recognize conditional classes

So I'm using TailwindCSS for a WP theme I'm developing.
I ran into an issue in creating the production grade theme files because, from how I understand the problem, purgecss can't recognize conditional classes used on template parts. For example, let's say I created a template part called "business-card.php" where I pass it a variable type (using set_query_var / get_query_var):
page-about.php
set_query_var('type', 'A');
get_template_part('template-parts/content/business', 'card');
set_query_var('type', 'B');
get_template_part('template-parts/content/business', 'card');
businesss-card.php
$type = get_query_var('type')
<div class="<?php echo type == 'A' ? 'text-color-A' : 'text-color-B' ?>">
--- insert some content here ---
</div>
So there will be two divs, one will have a text-color-A class, the other will have a text-color-B, both were created using a config file(rather than included in the base tailwind theme). This is fine in development -- since tailwind does actually create the utility color classes from the config file. But for some reason, when it's in production (i.e. purged & minified), it doesn't have those utility classes -- which were only used in the template part as conditional classes (and not in any other file).
PurgeCSS is intentionally very naive in the way it looks for classes in your HTML. It doesn't try to parse your HTML and look for class attributes or dynamically execute your JavaScript โ€” it simply looks for any strings in the entire file that match this regular expression:
/[^<>"'`\s]*[^<>"'`\s:]/g
That means that it is important to avoid dynamically creating class strings in your templates with string concatenation, otherwise PurgeCSS won't know to preserve those classes.
So do not use string concatenation to create class names:
<div :class="text-{{ error ? 'red' : 'green' }}-600"></div>
Instead, dynamically select a complete class name:
<div :class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
As long as a class name appears in your template in its entirety, PurgeCSS will not remove it.
See the docs for more details:
Writing purgeable HTML
If you are using Tailwind 2.0+ you can configure whitelisted classes that will be ignored by purge CSS directly inside of your tailwind.config.js file.
An example of my own code where I whitelist the class text-ingido-400 can be seen below
// tailwind.config.js
module.exports = {
purge: {
content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
options: {
safelist: ['text-indigo-400']
}
} ,
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
For more information you can check out the relevant documentation located at:
https://tailwindcss.com/docs/optimizing-for-production
You can use the PurgeCSS whitelist option to add those classes.
const purgecss = new Purgecss({
//... Your config
whitelist: ['text-color-A', 'text-color-B', 'etc']
})
Or the whitelistPatterns (Regex match)
whitelistPatterns: [/^text-color/], // All classes starting with text-color
You can find more information here
If you define your class names in a variable above where you want to use them it works akin to safe listing them in Tailwind or whitelisting them in PurgeCSS, is potentially easier to maintain, and works good in a pinch if you have a small number of possbile dynamic class names.
var classes =`grid-cols-1 grid-cols-2 grid-cols-3 grid-cols-4`
return (
<div className={`grid grid-cols-${items['grid-cols']}`}>
</div>
)
For some tailwindcss class, you can use inline style instead.
Inline style allow you to use dynamic value, like <div style="padding-left:{indent}rem">.
I think it works in php also. More details can be found here

Create LESS mixin with class in external file W3.css

I am creating a small personal project mainly with HTML and CSS, but I am new in this and have some problems. I want to use the W3.CSS framework but I don't want to explicitly use it in the html files (like <div class="w3-container">...) because I might want to use something else later and don't want to refactor every file. Googling I learned about less mixins I had the idea of using my own style.less file and from there import w3.css and inherit, for example, .w3-container class for header tags, which I believe cannot be done with only CSS. Anyway, what I am trying to do is:
#import "w3.css";
header {
.w3-container;
}
Both files, "style.less" and "w3.css", are on the same folder and I use the following command to try and compile it:
lessc style.less style.css
Which outputs the error:
NameError: .w3-container is undefined in <path to style.css> on line 3, column 2
I am probably not using less how it's supposed to be. I looked at other questions, for example this one but couldn't do it. I also noticed that my node.js and npm were really outdated: node: v0.12.4, latest: v5.11.0 npm: 2.10.1, latest: 3.8.7 but that wasn't it.
Why doesn't it work?
What other way can I avoid explicitly using classes such as "w3-container"?
Thanks.
Question part 1
With regards to the error:
NameError: .w3-container is undefined in on line 3, column 2
You've used .w3-container as a mixin, but the mixin hasn't been defined. You'd need to define the mixin like so:
#import "w3.css";
.w3-container() {
/*Styles to apply to the mixin would go here*/
}
header {
.w3-container;
}
However it doesn't sound like using a mixin was actually your goal.
Question part 2
With regards to your comment:
What other way can I avoid explicitly using classes such as "w3-container"
LESS compiles down to CSS, so there's no magic that LESS can provide in terms of selectors (such as aliasing W3.css), other than providing some extended functionality to reduce repetition and make your code more maintainable. If you don't want to add new CSS classes, your options are limited to using valid CSS selectors using a higher specificity. The example below is based on path. If w3.css contains:
header {
color: blue;
}
Then to target a header in a section you could use the more specific selector (in LESS):
section {
header {
color: orange;
}
}
This will compile to the CSS:
section header {
color: orange;
}
Question part 3
When you're trying to target an instance of an element of a particular class, it is important to prefix the class with & and include brackets for defining the properties to style like so:
header {
&.w3-container {
color: orange;
}
}
This will compile to the following CSS:
header.w3-container { color: orange; }
If you use .w3-container; by itself, LESS will assume you want to use a mixin here, and will throw the error from Question part 1 since there is no mixin defined with the name .w3-container.
#import (less) "w3.css";
header {
.w3-container;
}

SASS using a function within a variable definition [duplicate]

I'm trying Zurb Foundation 5.
So, I've created a new project and try changing settings. When I changed, for example, $row-width: rem-calc(1170); in my-project/scss/settings.scss, it compiled (in my-project/stylesheets/app.css) into:
.row {
max-width: rem-calc(1170);
}
It seems like it doesn't know about rem-calc function.
How to make it calculate rem-calc properly?
Your function doesn't exist. You must declare it (or import it from another file) before you use it. Sass does not throw errors for non-existent functions because they have a similar syntax to CSS functions. So it assumes that if it isn't a Sass function that it must be a CSS function.
Related: Test whether a Sass function is defined

Modifying content width of the Sphinx theme 'Read the Docs'

I am using 'Read the Docs' Sphinx theme for my documentation. In the original theme, given below
Read the Docs Sphinx Theme
the content or main layout width is designed to be mobile friendly. However, for my project I would like this to be a bit more wide. I do not know HTML and hence would appreciate if any one could give me some clues to increase the content (layout) width.
Another option is to create a stylesheet in source/_static with just the css you want, e.g.
.wy-nav-content {
max-width: none;
}
or
.wy-nav-content {
max-width: 1200px !important;
}
Make sure the directory is referenced in source/conf.py - I believe by default there's a line to do this, i.e.
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
Then create a custom layout in source/_templates/layout.html and do something like this to include your stylesheet
{% extends "!layout.html" %}
{% block extrahead %}
<link href="{{ pathto("_static/style.css", True) }}" rel="stylesheet" type="text/css">
{% endblock %}
Assuming you called your stylesheet style.css
In case someone is searching for a simpler answer...
combining the ideas from
https://samnicholls.net/2016/06/15/how-to-sphinx-readthedocs/
and the above suggestions, I found the easiest way of getting a custom window-width is the following:
In conf.py, add a function that adds a custom stylesheet:
def setup(app):
app.add_css_file('my_theme.css')
In conf.py, state/adjust:
html_static_path = ['_static']
Create a _static folder/directory if it doesn't exist.
Create a file called my_theme.css in the _static folder that contains the lines:
.wy-nav-content {
max-width: 1200px !important;
}
The HTML option added in Sphinx 1.8.0b1 (released Sep 2018) simplifies the process. The recommendation in Read The Docs Documentation is adding custom css to the theme via the html_css_files option in conf.py.
html_css_files = [
'custom.css',
]
Put the custom.css in the html static path folder (Default is _static folder).
Content of custom.css:
.wy-nav-content {
max-width: 75% !important;
}
First of all I must say, that during my sphinx quickstart I chose the option of separate folder for my sources and for my build.
It's a 3 steps process:
1. Create a document for your styles:
Where?
In the same directory where my conf.py lives, (in my case source), I created a folder for my custom static files (stylesheets, javascripts). I called it custom.
Inside it I created a subfolder for my stylesheets: source/custom/css.
In this subfolder I'm gonna create my custom styles: source/custom/css/my_theme.css.
2. Telling sphinx about it
Now we have to tell sphinx to spit this document inside build/_static/css, the same directory where is the stylesheet included in the Read The Documents theme. We do that adding the following line to conf.py:
html_static_path = ['custom'] # Directory for static files.
Done. Now, if we build, we will have the RTD styles (theme.css), and our custom my_theme.css in the same directory, build/_static/css.
3. Selecting our custom theme
Now we are gonna tell sphinx to use our custom my_theme.css, instead of the RTD one. We do that adding this line in conf.py:
html_style = 'css/my_theme.css' # Choosing my custom theme.
In our custom stylesheet, the first line should import the styles of theme.css with #import url("theme.css");.
And we are ready to start overwriting styles.
UPDATE: THERE IS AN EVEN SIMPLER WAY.
1. Put your customizations inside source/_static/css/my_theme.css.
In your custom stylesheet, the first line should import the styles of theme.css with #import url("theme.css");.
This way, you don't have to worry about messing up the default styles, if your custom stylesheet doesn't work, delete and start again.
2. Add the following line in conf.py:
html_style = 'css/my_theme.css'
The solutions here are somewhat hackish. If you want to include the style, and have a css override and have it work on RTD you will want something like this.
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_style = 'css/custom.css'
else:
html_context = {
'css_files': [
'https://media.readthedocs.org/css/sphinx_rtd_theme.css',
'https://media.readthedocs.org/css/readthedocs-doc-embed.css',
'_static/css/custom.css',
],
}
I have tested this myself and it appears to work locally and on RTD. Largely plagiarized from https://blog.deimos.fr/2014/10/02/sphinxdoc-and-readthedocs-theme-tricks-2/
source\conf.py
html_theme = 'sphinx_rtd_theme'
html_style = 'css/my_theme.css'
source\_static\css\my_theme.css
#import url("theme.css");
.wy-nav-content {
max-width: 90%;
}
That will be 90% width of your monitor.
I found myself repeating this customization on multiple projects I've worked on (based on the great answers here, of course ๐Ÿ˜ƒ ).
So I made an extension just for that, the usage is as follows:
pip install sphinx-rtd-size
And in the conf.py:
extensions = [
...
'sphinx_rtd_size',
]
sphinx_rtd_size_width = "90%"
Hoping this might simplify things for future users...
You can checkout the pypi page and the github repository.
For 'classic' Theme, The solution is as simple and as clean as :
# Add/Update "html_theme_options" like this on your conf.py
html_theme_options = {'body_max_width': '70%'}
Adapt the percentage to your taste.
Reference from sphinx: body_max_width (int or str): Maximal width of the document body. This can be an int, which is interpreted as pixels or a valid CSS dimension string such as โ€˜70emโ€™ or โ€˜50%โ€™. Use โ€˜noneโ€™ if you donโ€™t want a width limit. Defaults may depend on the theme (often 800px).
To make the ReadTheDocs theme use the entire width of your screen you can modify the theme.css file, removing the max-width: 800px; property from the wy-nav-content class definition, like so:
.wy-nav-content {
padding: 1.618em 3.236em;
height: 100%;
/* max-width: 800px; */
margin: auto;
}
Some Notes
Source of theme.css is here:
https://github.com/rtfd/readthedocs.org/blob/master/media/css/sphinx_rtd_theme.css
On your filesystem it will be in (assuming you've run:pip install sphinx_rtd_theme):
lib/python2.7/site-packages/sphinx_rtd_theme/static/css/theme.css
To find the absolute path of theme.css on Linux/Mac you can run this on the command line (assuming you have set your $PYTHONPATH environment variable):
for p in `echo $PYTHONPATH | tr ":" "\n"`; do
find $p -type f -name 'theme.css' | grep sphinx_rtd_theme
done
The theme.css file will be minified so you can use a tool like http://unminify.com to make it easier to read.
The results:
Before:
After:
I would modify this in the css. You should search for the file theme.css (it is in the read-the-doc sources at "sphinx_rtd_theme/static/css/theme.css").
Make a copy of that file and put it in your sphinx _static dir. In that css file you can make all the layout changes that you need. (You might have to read a bit on css files if you have never worked with that.)
Hope this helps.