Repeat numerically increasing CSS classes with similarly named background image assets - css

Is it possible with Emmet to shorthand this CSS? Each class corresponds to an image asset and they share an increasing number.
.penguin1 { background-image:url('penguin_pngs/mound_1.png'); }
.penguin2 { background-image:url('penguin_pngs/mound_2.png'); }
.penguin3 { background-image:url('penguin_pngs/mound_3.png'); }
.penguin4 { background-image:url('penguin_pngs/mound_4.png'); }
.penguin5 { background-image:url('penguin_pngs/mound_5.png'); }
.penguin6 { background-image:url('penguin_pngs/mound_6.png'); }
.penguin7 { background-image:url('penguin_pngs/mound_7.png'); }
.penguin8 { background-image:url('penguin_pngs/mound_8.png'); }
I am able to use CSS shorthand such as bgi which expands to background-image: url(); but is it possible to repeat the classname and use a numbering operator such as Emmet's html $ operator?

Related

Less variables in selector with &

I want to use the & to attach a pseudo :not to the parent class however I don't know how to do this when using mixins and variable selectors.
.hideElement(#selector, #maxWidth) {
#media (max-width: #maxWidth) {
#{selector} {
display: none;
}
}
}
.jp-sleek.jp-audio:not(.jp-state-no-volume-support) {
.hideElement(~':not(.jp-state-full-screen) .jp-title-container', 580px);
}
The output I want is:
.jp-sleek.jp-audio:not(.jp-state-no-volume-support):not(.jp-state-full-screen) .jp-title-container {
display: none;
}
The current output is (notice the space in the :not):
.jp-sleek.jp-audio:not(.jp-state-no-volume-support) :not(.jp-state-full-screen) .jp-title-container {
display: none;
}
I know I need to use the & selector but this doesn't work:
.hideElement(~&':not(.jp-state-full-screen) .jp-title-container', 580px);
How do I do this?
Full code for context:
.jp-sleek.jp-video,
.jp-sleek.jp-audio.jp-state-no-volume-support {
.hideElement(~'.jp-repeat', 400px);
.hideElement(~':not(.jp-state-full-screen) .jp-title-container', 530px);
.hideElement(~'.jp-download', 580px);
}
.jp-sleek.jp-audio:not(.jp-state-no-volume-support) {
.hideElement(~'.jp-full-screen', 400px);
.hideElement(~'.jp-repeat', 450px);
.hideElement(~':not(.jp-state-full-screen) .jp-title-container', 580px);
.hideElement(~'.jp-download', 630px);
}
The & cannot be used as a parameter to a mixin or as part of the parameter to a mixin. When used in that way the & would have no special meaning. It wouldn't resolve to the parent selector and will just remain as &. Plus the below line is incorrect because the ~ must be followed by a ".
.hideElement(~&':not(.jp-state-full-screen) .jp-title-container', 580px);
I'd strongly urge you to have a look at the alternate method suggested by seven-phases-max in his comment. But a very simple solution to your problem while retaining your code-base as-is will be the following. Just take the &:not(...) part out, put it as its own block and then invoke .hideElement mixin within this block with just the other part of the selector (the child selector) as input.
.jp-sleek.jp-video,
.jp-sleek.jp-audio.jp-state-no-volume-support {
.hideElement(~'.jp-repeat', 400px);
&:not(.jp-state-full-screen){ /* take the not part out and put it as a block */
.hideElement(~'.jp-title-container', 530px);
}
.hideElement(~'.jp-download', 580px);
}
.jp-sleek.jp-audio:not(.jp-state-no-volume-support) {
.hideElement(~'.jp-full-screen', 400px);
.hideElement(~'.jp-repeat', 450px);
&:not(.jp-state-full-screen) { /* take the not part out and put it as a block */
.hideElement(~'.jp-title-container', 580px);
}
.hideElement(~'.jp-download', 630px);
}

SCSS and direct nesting

I'm stuck on this one. I know I have an ability to reach all the way outside of the nested operators to add a prefix class like:
.myEl {
html.no-touch & {
}
}
and that will output:
html.no-touch .myEl {}
but I'm wondering if there is a way to escape by only one level, rather than all of them. Given this sort of input:
.myEl {
.myEl3 {
.myEl2 {} /* direct parent operator goes here? */
}
}
I would expect this sort of output:
.myEl1 .myEl2 .myEl3 {}
Is this possible?
Unfortunately, this is not possible in SASS. You'd probably have to do something like this if you don't want to nest further (which I'm sure you already knew).
.myEl1 {
.myEl3 {
/* Base styles here */
}
.myEl2 .myEl3 {
/* Specific styles here */
}
}

Wildcard nested selector

I have the following bit of Sass code :
.c-panel-menu-c {
&.grid_6 {
float: right;
}
}
i need to have float right applied to all grids that start with grid_ . The float should only be set when the grid class is applied to an element that also has c-panel-menu-c.
I wanted to use a wildcard selector like
div[class*='grid_'] {
float:right
}
But am not sure if it's possible the way i need it. Something like
.c-panel-menu-c {
&.div[class*='grid_'] {
vertical-align: top;
}
}
Which doesnt work.
Thank you for any tips/advice.
the problem is the tag name ... you can not concatenate a tag name, for example div, at the end of another selector, like you would with a class name. Let's look at your example:
.c-panel-menu-c {
&.grid_6 {
...
}
}
will return
.c-panel-menu-c.grid_6 { ... }
which is a valid selector. But attaching 'div' at the end (lets leave out the attribute selector part for now)
.c-panel-menu-c {
&div {
...
}
}
does not make sense (and it also isn't possible in Sass, hence you get an error) as the tag name should always be before the class or id selector. This does not change if we add an attribute selector statement, so that's why it does not work the way you tried &div[class*='grid_'].
What you can do, is add the attribute selector directly to the preceding class name, like so:
.c-panel-menu-c {
&[class*='grid_'] {
...
}
}
which would compile to:
.c-panel-menu-c[class=*'grid_'] { ... }
and select everything that has the class .c-panel-menu-c and a class containing with grid_.

Is possible to make an important property value from CSS selector a non important one?

Is possible to make an important property value from CSS selector a non important one?
For example: Bootstrap 3 defines .hide class as:
.hide { display: none !important; }
Is possible to remove the important value without modifying the BS3 source code?
Thinking at somethingl iike
.hide { display: none !remove-important; }
Note that I want to keep the same value! I don't want to set block !important to .hide class because that would not be correct...
I already added a new class .hide-non-important and used it where it was needed:
.hide-not-important { display: none; }
...but the question is: is there any alternative to this?
You don't need to edit the original source code. Just create a stylesheet and place it after the Bootstrap stylesheets and add this to it:
.hide { display: block !important; }
Now, having said this, I would be very careful about doing this. You don't know how many elements across your site have applied this class, and you will almost certainly get unanticipated results.
There is obviously a reason that this class has been applied, I would suggest either:
don't do this
add some other class to the element and add styles to that. Adjust your markup (or use js to apply the class if need be) to something like:
<div class="hide custom-hide-reset"></div>
Then add this style to the stylesheet you've created:
.custom-hide-reset { display: none; }
You can overwrite this with:
body .hide { display: none !important; }
.someclass.hide { display: none !important; }
those two examples have higher priority
The stylesheet objecs are accessible from javascript
var sheets = document.styleSheets
Once you have the stylesheet array, you can iterate over the rules
var rules = sheets[i].cssRules || sheets[i].rules // browser dependency
Each rule has a style property, which is mutable in the usual way.
rule.style[cssPropName] = value;
There is a method on the sheet to delete a rule by index, either deleteRule or removeRule, depending on the browser.
Bottom line, you can find the rule and either edit it or delete and re-add it in a modified form.
Reference: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml#.Ujsin4ZmjAs
Since the question can be splitted in
how can I remove !important from a rule applied to my page but
without changing its value and
without editing the original CSS file
For pure spirit of adventure only, I think it would be possible in the following way:
load the CSS with jQuery;
perform a replacement of its content, by searching .hide { display: none !important; } and replacing it with .hide { display: none; };
apply the new in-memory altered CSS to the page.
Taking for good the solution posted in this answer, it could be modified with something (totally untested, just to get the idea) like:
$.get(myStylesLocation, function(css)
{
var alteredCss = css.replace(".hide { display: none !important; }",".hide { display: none; }");
$('<style type="text/css"></style>')
.html(alteredCss)
.appendTo("head");
});
You can override the current !important value by another one like
.col{ color:red !important; }
.col{ color:green; } // wont work
.col{ color:blue !important; } // will work and set color blue instead of red
DEMO.
Update :
This question is not about JavaScript but as an alternative you can accomplish the task using these technique, remove the rule using JavaScript and then add a new rule again.
function getCSSRule(ruleName, deleteFlag) {
ruleName=ruleName.toLowerCase();
if (document.styleSheets) {
for (var i=0; i<document.styleSheets.length; i++) {
var styleSheet=document.styleSheets[i];
var ii=0;
var cssRule=false;
do {
if (styleSheet.cssRules) {
cssRule = styleSheet.cssRules[ii];
} else {
cssRule = styleSheet.rules[ii];
}
if (cssRule) {
if (cssRule.selectorText.toLowerCase()==ruleName) {
if (deleteFlag=='delete') {
if (styleSheet.cssRules) {
styleSheet.deleteRule(ii);
} else {
styleSheet.removeRule(ii);
}
return true;
} else {
return cssRule;
}
}
}
ii++;
} while (cssRule)
}
}
return false;
}
function killCSSRule(ruleName) {
return getCSSRule(ruleName,'delete');
}
function addCSSRule(ruleName, v) {
if (document.styleSheets) {
if (!getCSSRule(ruleName)) {
if (document.styleSheets[0].addRule) {
document.styleSheets[0].addRule(ruleName, v,0);
} else {
document.styleSheets[0].insertRule(ruleName+'{'+v+'}', 0);
}
}
}
return getCSSRule(ruleName);
}
// Check the rule before deleting
console.log(getCSSRule('.col')); // .col { color:red !important; }
// At first remove the current rule
killCSSRule('.col');
// Now assign nre rule
addCSSRule('.col', 'color: red');
// Check the rule after deleting
console.log(getCSSRule('.col')); // .col { color:red; }
DEMO. ( Source : Totally Pwn CSS with Javascript )

Defining Variable Variables using LESS CSS

Say I have three separate color schemes that are used on various pages in a site. Each color has a a light, medium and dark tint defined, and the color scheme is defined by a class in the body. Assume that the "red" color scheme is the default. Like this:
Color Definitions:
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
Basic Default Style Example
body { background-color: #red-dk;
#container { background-color: #red-md;
p { color: #red-dk; }
}
}
Different Color Scheme Style Example
body.green { background-color: #green-dk;
#container { background-color: #green-md;
p { color: #green-dk; }
}
}
I'd like to use variables so that I don't have to re-write all of the color variations for each scheme, so that I can just write something like this:
body.[color-var] { background-color: #[color-var]-dk;
#container { background-color: #[color-var]-md;
p { color: #[color-var]-dk; }
}
}
…but I can't quite wrap my head around how to accomplish that. Help…?
Use interpolation and escaping, parentheses in the selector and parametric mixins to get the desired effect:
Dynamic variables by interpolation: In a string, "#{variable}" is replaced with the value of the variable. They can also be nested: Given #{#{var}-foo} and #var: bar;, the result is "barfoo".
The resulting value is quoted. To remove these quotes, prefix ~.
Dynamic selectors by Selector interpolation: body.#{var} turns into body.bar.
Example:
#red-md: #232;
#red-dk: #343;
.setColor(#color) {
body.#{color} { background-color: ~"#{#{color}-dk}";
#container { background-color: ~"#{#{color}-md}";
p { color: ~"#{#{color}-md}"; }
}
}
}
.setColor(~"red"); // Escape to prevent "red" turning "#FF0000"
//.setColor(~"blue"); etc..
Turns into:
body.red {
background-color: #334433;
}
body.red #container {
background-color: #223322;
}
body.red #container p {
color: #223322;
}
Note: When the answer was originally written, selector interpolation did not exist. See the previous revision for the solution if you're working with an old LESS compiler (before LESS 1.3.1a). Support for the old method will be dropped in LESS 1.4.0.
If those values really follow a predictable format like that, seems like a perfect case for a parametric mixin:
Less:
#red: #232;
#green: #565;
#blue: #898;
.theme (#color) {
background-color: #color - #111;
#container {
background-color: #color;
p { color: #color + #111; }
}
}
body.red {
.theme(#red);
}
Compiled CSS:
body.red{background-color:#112211;}
body.red #container{background-color:#223322;}
body.red #container p{color:#334433;}
I know this question is pretty old, but for those that come to this post my answer maybe can help
I`m not really sure for what you want to use this, but one of my suggestion is based on #ScottS answer. On my real world, I need to create a web app, where it would show several brands and each brand have their own text color, background and so on... so I started to chase a way to accomplish this in LESS, what I could easily do on SASS and the result is below:
LESS
// Code from Seven Phase Max
// ............................................................
// .for
.for(#i, #n) {.-each(#i)}
.for(#n) when (isnumber(#n)) {.for(1, #n)}
.for(#i, #n) when not (#i = #n) {
.for((#i + (#n - #i) / abs(#n - #i)), #n);
}
// ............................................................
// .for-each
.for(#array) when (default()) {.for-impl_(length(#array))}
.for-impl_(#i) when (#i > 1) {.for-impl_((#i - 1))}
.for-impl_(#i) {.-each(extract(#array, #i))}
// Brands
#dodge : "dodge";
#ford : "ford";
#chev : "chev";
// Colors
#dodge-color : "#fff";
#ford-color : "#000";
#chev-color : "#ff0";
// Setting variables and escaping than
#brands: ~"dodge" ~"ford" ~"chev";
// Define our variable
.define(#var) {
#brand-color: '#{var}-color';
}
// Starting the mixin
.color() {
// Generating the loop to each brand
.for(#brands); .-each(#name) {
// After loop happens, it checks what brand is being called
.define(#name);
// When the brand is found, match the selector and color
.brand-#{name} & {
color: ##brand-color;
}
}
}
.carColor {
.color();
}
Te result will be:
CSS
.brand-dodge .carColor {
color: "#fff";
}
.brand-ford .carColor {
color: "#000";
}
.brand-chev .carColor {
color: "#ff0";
}
This is very tricky and I had to use several elements to get what I needed, first used a set of mixins provided by Seven Phase Max and you can find it here and than, the #ScottS answer was the piece that was missing fro my puzzle... hope this helps you and others that need to create a set of Variables to be part of another variable and create a more dynamic less file.
You can copy my entire code and test at http://lesstester.com/
Try this
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
#color: 'red-lt';
div{
background: ##color;
border: 1px solid lighten(##color,20%);
}
To my knowledge, variable variable names are not supported in LESS. You could however restructure your declarations in a more semantic manner:
/* declare palette */
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
/* declare variables based on palette colors */
#lt: #red-lt;
#md: #red-md;
#dk: #red-dk;
/* ...and only use them for main declarations */
body { background-color: #dk;
#container { background-color: #md;
p { color: #dk; }
}
}
This should let you switch between palettes quite painlessly by avoiding explicit color references.

Resources