How can I overrule a LESS variable within a mixin? - css

I'm using LESS in one of my projects right now and I need to create some colour-schemes for different users. I'm building a portal and based on what kind of user logs in, the colour-scheme needs to change.
So in my mixins.less (which I can't modify) file I have:
#color-button-bg: #333;
#color-button-txt: #fff;
#color-button-fs: 1.5rem;
#color-button-fw: 500;
#color-button-hover-pct: 10%;
.base-btn-default(#type: button) {
background: ~"#{color-button-bg}";
border: 1px solid ~"#{color-button-bg}";
color: ~"#{color-button-txt}";
font-size: ~"#{color-button-fs}";
font-weight: ~"#{color-button-fw}";
&:hover, &:focus {
#color-btn-hover: ~"color-button-bg";
#color-btn-hover-pct: ~"color-button-hover-pct";
background: darken(##color-btn-hover,##color-btn-hover-pct);
border-color: darken(##color-btn-hover,##color-btn-hover-pct);
color: ~"#{color-button-txt}";
}
}
And in a separate file with client-specific mixins I tried the following:
/* Override default color with theme-color */
.theme-styling() {
#color-button-bg: #main-theme-color;
}
Then finally I wanted to add a class to my <body> tag and style the colour-scheme based on that classname:
body.theme-a {
#main-theme-color: teal;
.theme-styling();
}
However, this doesn't seem to work. I think it has something to do with scoping / Lazy evaluation, but I'm not that experienced in LESS yet, to see where my error is.
I created a Codepen for it, without the separate files and in a bit of a simplified form:
https://codepen.io/jewwy0211/pen/JVNZPv

I've just played around with your codepen a bit. When you define the variable in your mixin, it does work, the problem is that you then don't use that variable in the mixin or in the class that contains the mixin.
So, if you've got 2 buttons like this:
<div class="wrapper one">
<button>Theme 1</button>
</div>
<div class="wrapper two">
<button>Theme 2</button>
</div>
You can call their theme-specific variable mixins in their respective classes to get the vars set, but you then must use the vars within the same class:
.wrapper.one {
.theme-styling-1();
background-color: #color-button-bg;
}
.wrapper.two {
.theme-styling-2();
background-color: #color-button-bg;
}
/* Theme Vars */
.theme-styling-1() {
#color-button-bg: teal;
}
.theme-styling-2() {
#color-button-bg: red;
}
EDIT: Here's a codepen: https://codepen.io/mmshr/pen/OGZEPy

Related

How to select specific class prefix while excluding other prefix?

I need to select the body element when it has a class beginning with post-type- but not select it when there's also a class beginning with taxonomy-. Does anyone know how to get this to work?
body[class^="post-type-"],
body[class*=" post-type-"] {
&:not([class^="taxonomy-"]),
&:not([class*=" taxonomy-"]) {
.widefat {
.check-column {
display: none;
}
}
}
}
EDIT: 0stone0's answer below helped me realize the CSS it was outputting was completely wrong, so this new approach is working well:
body[class^="post-type-"]:not([class^="taxonomy-"]):not([class*=" taxonomy-"]),
body[class*=" post-type-"]:not([class^="taxonomy-"]):not([class*=" taxonomy-"]) {
.widefat {
.check-column {
display: none;
}
}
}
div[class*='post-type-']:not([class*="taxonomy-"])
This pure CSS should target the desired element
Select classes that contain post-type-, but not() containing taxonomy-
div[class*='post-type-']:not([class*="taxonomy-"]) {
border: 1px solid red;
}
<div class='post-type-something'>post-type-something</div>
<div class='post-type-something taxonomy-foobar'>post-type-something taxonomy-foobar</div>
<div class='taxonomy-foobar post-type-something'>taxonomy-foobar post-type-something</div>
Note: Demo uses <div> instead of <body> and applies a border when targeted

Advanced SCSS structure: E.g. dynamic variables depending on the existence of a specific parent/outer class

I'm trying to find out whether the following logic, that would allow for a more modular approach, can be implemented or not:
Challenge:
I got three major categories in my app: running, swimming, biking, each with their own theme/color, e.g.
scss:
$category-colors: (
'running': red;
'swimming': blue;
'biking': green;
)
Throughout the app, specific components and nested components should adapt e.g. their background-color to the color of the context, meaning to the color of one of the categories. The following is one such component:
html:
<div class="running">
<div class="form">
<div class="form__header">
<h3>New</h3>
</div>
<div class="form__content">
<p>Some text</p>
</div>
</div>
</div>
scss:
.form {
&__header {
height: 100px;
// 'running' is not available here but it illustrates what I'm trying to achieve
background: map-get($category-colors, 'running');
}
&__content {
height: 50vh;
}
}
The background color should be dynamically set depending on the presence of the parent/grandparent/n-parent running. Is there any way to get 'category' dynamically?
I could to add a suffix for the class that should adopt that theme/color like form__header_running but I couldn't find a way to extract "running" as a variable to then map the color.
I tried something like the following, but the variables somehow always ends up to be the last one in that chain, meaning 'biking', even if biking is not present on the parent.
.form {
$bgColor: black !default;
.running & {
$bgColor: map-get($category-colors, 'running')
}
.swimming & {
$bgColor: map-get($category-colors, 'swimming')
}
.biking & {
$bgColor: map-get($category-colors, 'biking')
}
&__header {
height: 100px;
background: $bgColor;
}
&__content {
height: 50vh;
}
// image much more children/sub children, so the simple use of $bgColor would be much more efficient
}
Any idea/concepts on how to achieve what I want?
Any inputs on a styling structure/architecture you would choose for a larger app with similar demands?
Looking forward to a discussion!

Where do these styles come from in reactjs examples on codepen?

Composition-vs-inheritance React
Documentation
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
https://codepen.io/gaearon/pen/ozqNOV?editors=0010
When you're viewing a pen on CodePen, the styling will most likely be applied by the code in the CSS section. It's possible that there is inline CSS in the HTML, and it's also possible JavaScript is manipulating the styling inline, but in all three instances you'll be dealing with CSS code.
The example you posted is doing all of the styling in the CSS tab. The HTML tab only contains a container for the React elements to render to.
We'll use your FancyBorder function as an example.
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
You're constructing a <div> with the class name of 'FancyBorder-' + props.color, where props.color is a variable that will be used later on.
Continuing with your example, you use the following code to create a welcome dialog:
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1>
Welcome
</h1>
</FancyBorder>
);
}
In this code, you're calling the FancyBorder function and passing through color="blue" which is referenced in the original function as props.color. It now runs 'FancyBorder-' + props.color to generate a class named: FancyBorder-blue.
Now in the CSS section, you'll see your FancyBorder-blue is already setup as a class and has styling applied to it:
.FancyBorder-blue {
border-color: blue;
}
This specific CSS applies a blue border around the box we just created. Hopefully that clears things up.
Figured it out. Those styles when opened in CodePen in edit mode are not visible when tabs are minimized. It's enough to drag them open or change the link so they are opened by default. Just a CodePen feature =)
See the difference:
https://codepen.io/gaearon/pen/ozqNOV?editors=0010
https://codepen.io/gaearon/pen/ozqNOV
.FancyBorder {
padding: 10px 10px;
border: 10px solid;
}
.FancyBorder-blue {
border-color: blue;
}
.Dialog-title {
margin: 0;
font-family: sans-serif;
}
.Dialog-message {
font-size: larger;
}

What is the LESS equivalent of declaring var in CSS?

I have a scenario to change the branding color and few other styling variables on the portal at run time based on some conditions. I'm able to achieve that
using CSS (look at the below sample snippet).
But since all our CSS are generated by converting the LESS files at compile time, not sure on how to write a similar logic in LESS so that it generates the CSS like below?
:root {
--brand-color: yellow;
}
h1 {
color: var(--brand-color);
}
<h1 id="demo">Hello</h1>
<button onclick="myFunction()">Click me</button>
function myFunction() {
document.documentElement.style.setProperty('--brand-color', 'red');
}
#yellow-color: yellow;
#red-color: red;
h1{
color: #yellow-color;
&.red-color{
color: #red-color;
}
}
Add class instead
function myFunction(){
$("myelement").addClass("red-color");
}

Event items with different CSS

I have the following CSS to show a whole event as "completed".
.afc-completed,
.fc-agenda .afc-completed .fc-event-time,
.afc-completed a {
color: yellow; /* text color */
background-color: #6C3; /* default BACKGROUND color #36c */
text-decoration: line-through;
}
How do I write a CSS for only changing the fc-event-title only?
I saw my class afc-completed is added to the <div> element, but I don't find a solution to just change the title (fc-event-title) or the time.
Any help here?
Günter
#wsanville & #Thomas
I think that's not that simple, sorry.
Just defining what wsanville said will change for all events. The point is to change only for "completed" events.
For that I have
if (newEvent.completed != null) {
newEvent.className = "afc-completed";
}
But that's going to the div and not to title only.
I think I need to add a class directly to/or instead of the '.fc-event-title' for just only those selected/completed events, and only to the title.
Here is a typical div:
<div style="position: absolute; z-index: 8; left: 144px; width: 135px; top: 40px;"
class="fc-event fc-event-hori fc-corner-left fc-corner-right afc-completed ">
<a><span class="fc-event-time">15:15 - 16:15<br></span>
<span class="fc-event-title">Fri Dille</span>
</a>
<div class="ui-resizable-handle ui-resizable-e" unselectable="on"
style="-moz-user-select: none;">
</div>
</div>
But the newEvent.className doesn't work like that!
Is there another possibility?
And I need more modifications to the event presentation, like additional icons or text with italic ... and different combinations of those 'options'.
Thanks for your help.
Günter
OK, here is a working solution to solve for "important" and "completed" attributes of the event:
newEvent.className = ((newEvent.completed != null)? "afc-completed " : "")
+ ((newEvent.priority != null) ? "afc-important " : "");
and
.afc-completed .fc-event-title {
color: yellow;
background-color: #A6B5BC; /* grey */
text-decoration: line-through;
}
.afc-important .fc-event-title {
color: #C00 !important;
font-weight: bold !important;
}
Thanks for helping ;)
If you post some of your markup, I can give a better answer, but in the general case, you will need to add an additional rule to your stylesheet that applies to elements with the fc-event-title class. Something like this:
.fc-event-title
{
color: #ff0000; /* change the color values to something more appropriate */
background-color: #00ff00;
text-decoration: line-through;
}

Resources