Error "stack level too deep" when compiling sass with nested SUSY calls - jruby

I have found in a particular .scss file I'm working with that whenever I call #include span(...) inside of #include with-layout(...), like such
#include with-layout(10 0 split){
div.header{
#include span(8 of 10);
}
}
I receive the following error:
error myFile.scss (org/jruby/RubyArray.java:2339:in `collect': stack level too deep)
This leads me to believe there is some sort of infinite recursion occurring with these particular nested properties. Does anyone know how this should be fixed, or what the proper way to nest these #include statements is? Thanks!

Can you post your mixin definitions?
My guess is that your span mixin contains a #content directive, causing an infinite loop:
Your code applies the div.header {} content block to all #content directives located in the with-layout mixin, but if each div.header {} block contains a #content directive via the span mixin, SASS will keep replacing each #content directive with a div.header containing a #content directive, etc. etc.
This could be fixed by removing the #content directive from your span mixin, or defining a new span mixin that doesn't contain a #content directive.

Related

Is there any way to create dynamic utility classes in css?

Is there any way to do something like...
<h1 class="pad-5">Some Heading</h1>
to apply a padding of 5px to the h1 tag.
And this should be dynamic. For example, If I write class="pad-15", it should give padding of 15px.
And I want to do this by creating one single ruleset. Not by defining different classes of pad-5, pad-15 and so on individually.
In css file, it should be something like...
.pad-[$value]{
padding: $value;
}
So, is there any way of doing this?
No, you cannot do this with CSS. You could use a CSS preprocessor such as SASS or Less to generate a bunch of classes for you in a loop if you want. You could alternatively use JS to add styling based on the class name, though I would definitely not recommend it.
SASS (SCSS) example:
#for $i from 1 through 15 {
.pad-#{$i} {
padding: $i;
}
}
Use a mixin (with Sass):
https://sass-lang.com/documentation/at-rules/mixin
Example:
#mixin pad($width) {
padding: #{$width}px;
}
Application:
h1{
#include pad(5);
}

Overriding class definitions with Less

I'm trying to customize a Joomla template, which is based on Bootstrap. Specifically, I'm trying to make a "hardcoded" .span4 have the width of a .span3. Sure, it would be much easier to change the markup, but I think that's what css is for, despite the way most of us use Bootstrap for defining layout and visual appearance. Besides, where would be the fun of learning?
For that, this is what I'm trying in the my_css.less provided with the template:
.row-fluid #top1.span4 {
.row-fluid .span(3);
background:red;
}
Actually, the "background" bit is only to make sure that I'm not getting the selector wrong. So, I get that element with a red background, but the rest of the properties aren't applied. This is what I get instead:
.row-fluid .span4 {
width: 31.623931623932%;
}
Am I doing anything wrong? Is what I'm trying even possible?
Thank you!
* Edit *
This is the template I'm using in my page:
Perty by SmartAddons
The bit I'm trying to customize is the one at the right of the logo, the one holding the language selector and the social icons.
My client's logo is wider than the one in the template example, so it pushes #top1 to the right, and it pushes the following element (the one containing "galleries", "my account" and the search box) below.
Answering #Harry's question about selectors not matching, mine is ".row-fluid #top1.span4" because I only want my modification to apply to the .span4 contained in #top1. The other piece of code I pasted below is what is being applied instead of what I intend. Also, I wanted my customization to take preference over the default css, so my selector tries to be more specific. It doesn't seem to be wrong, because the background of the element becomes red.
#Harry:
Also, are you using any mixins to generate the width?
I'm not experienced in Less and I wasn't able to find the mixin in bootstrap documentation, but according to #freejosh at this post:
In mixins.less there's a mixin called .span(#columns) that's used to calculate the width, depending on #gridColumnWidth and #gridGutterWidth along with the argument.
Actually, that example is the one I'm trying to adapt to my needs.
I hope my edition made things clearer (or at least not more obscure, english is not my native language).
Thank you again!
* Edit 03/09/2014 *
Ok, I think I'm gettin closer. New code:
.row-fluid #top1.span4 {
#grid > .fluid > .span(3);
background:red;
}
Resulting css:
.row-fluid #top1.span4 {
width: * 3 * 2;
background: red;
}
Of course, the browser complains of an invalid property value. But at least that is a step (forward?)
#grid > .fluid > .span(3);
gives me:
.row-fluid #top1.span4 {
width: 23.40425532%;
*width: 23.35106383%;
background: red;
}
and NOT width: * 3 * 2;
Tested with less.php, less v1.4, v1.7.3. Notice that Less v2 do not compile BS2 at all.
Less v2 fails on #grid > .core > .span(#gridColumns); in navbar.less

How do I maintain modularity with mixins?

I'm creating a SASS mixin library for my team to use in CSS classes of their choosing. I'm realizing that preventing style contamination is more difficult than I thought.
Without a preprocessor it's easy for me to separate these two styles
.button { color: red; }
.link { color: blue; }
Now, I want to create mixins for each style
#mixin button()
color: red
#mixin link()
color: blue
Seems simple enough, but I have no control over how the mixins will be assigned to classes. The user may choose to do this:
SASS
.btn
#include button()
ul.nav > li > a
#include link()
HTML
<ul class="nav">
<li>
Home
</li>
<li>
<a class="btn" href="">Save</a>
</li>
</ul>
Now the button inherits the link styles. Of course, there are a few things I can do with the CSS to "fight" this inheritance, but I'm interested more in an overall technique to namespace mixin styles (if possible).
Having worked on this for a while (long before posting this question), I'll post my own administrative workaround, if not a total solution:
Enforce in your styleguide that naked element selection (e.g. "div {...}) is not allowed. Users will need to do as such:
SASS
#mixin button()
color: red
#mixin link()
color: blue
.btn
#include button()
ul.nav > li > a.nav-link
#include link()
Unfortunately, this adds more classes to the HTML.
Update
I came to hate the above method. Direct descendent selectors all over the place tightly couple the proximity of elements.
The cleanest way I can think to solve this problem is to eschew content-descriptive classes for elements (as opposed to blocks.)
After all, Blocks like navbars and modals can mean all kinds of things, but what other class do you need to describe a button? Perhaps mixins on the button should be deferred to modifiers on the button.
.button
// This has already been defined by the underlying framework.
.button.send-form
#include button-primary()
// This is a special button so we'll move in the primary color and a drop shadow.

How to reuse css class content in another class without copying?

Is it possible to use existing css class as content in another class ?
I mean something like:
/* Contained in some library: */
.class1 { text-indent: 100 }
/* I can not change this: */
<span class="class2">
The definition for class2 is also contained in another library. So I can not change it directly.
/* But I want to do something like that in my CSS file: */
.class2 { .class1 }
I know it is not possible in that form. But maybe one can use some trick to achieve the behaviour without copying of the content of class1? I need this because I want to redefine class with content from another CSS class. Our project uses jQuery as well, but I would do it rather with CSS.
EDIT: I should explain more, I could not change how .class1 is defined, because this class is in a library, and I could not change mark up on span class.
It is imposible to do in standard CSS what you are commenting, as there is not pure inheritance.
Despite it doesn't apply with your code restrictions, this is the closer way to do it:
.class1, .class2 { text-indent: 100 }
.class2 {
/* Styles you want to have only in class 2 */
}
<span class="class2" />
On the other hand, as #A. Wolff has pointed out, you can still use js/jq to add class to specific elements: $(function(){$('.class2').addClass('class1')}); Then just set a specifc CSS rule for these elements.
In case you don't want to use JS, for something like that you'd need to use SASS or similar, which "compiles" to CSS.
CSS has no means to reference one rule-set from another.
Your options include:
Using multiple selectors for things with common rules
.menu,
.nav {
font-weight: bold;
}
.nav {
display: inline-block;
}
Using multiple classes on a single element
.menu {
font-weight: bold;
}
.nav {
display: inline-block;
}
<li class="menu nav">
Generating your CSS programatically
For example, with SASS
#mixin menu {
font-weight: bold;
}
.nav {
display: inline-block;
#include menu;
}
Yes, it is possoble.
Write:
.class1,.class2 {text-indent:100;}
.class1{color:red;}
.class2{font-size:30px;}
More info here.
Another option is to use LESS to do this. It's a very good tool and do some improvements to your CSS development.
Take a look at theirs documentation, it's very nice. About the compilers, I use Koala and recommend it.
You mentioned in one comment that you cannot use LESS, but I think perhaps you misunderstand how LESS (or another preprocessor) could help you. That is, you have not given any reason that I can see why you cannot use it (even in your update). As I understand your problem, you have the following parameters:
Cannot change html
Cannot change the css file that defines .class1.
You can change the css file that defines .class2.
If the above is correct, then here is how you use LESS (version 1.5+). You make your file defining .class2 a .less file. Then, to keep it clean, I believe you are going to have to do a two step process (it may be you can do step 2 without step 1).
Step One: Make the CSS into LESS
Create a file, let's say CSStoLESS.less and put this in it:
#import (less) /path/to/your/your-css-defining-class1.css;
This will import the css and make the processor consider it as LESS code. It is possible that the next step does that as well, I have not had opportunity to test it out.
Step Two: Use that file as reference in your LESS
By doing this in your .less file defining .class2:
#import (reference) /path/to/your/CSStoLESS.less;
.class2 { .class1; }
You are importing the previous css file that has been converted to less as reference only. This prevents you from getting duplicate selectors for .class1 or anything else contained in your original css file. Now you can use an inclusion of .class1 just like you show in your question to make the properties of .class1 become that of .class2.
It may be that this alone works:
#import (reference) /path/to/your/your-css-defining-class1.css;
.class2 { .class1; }
What I don't know is if the (reference) inclusion also defaults to making .css into LESS code like the (less) inclusion typecasting does in step one. I need to research this out more. If so, then it is a one-step, not a two-step process.
The best way would be to redeclare class1 just below your custom css ends and override it with the values that you are looking for. This way, the inherited values, that you cannot change + the values that you need to incorporate, both shall apply.
I am assuming you want whatever is in .class1 plus some extra properties in .class2
One way is to simply apply both classes to the element you want..
<span class="class1 class2" />
another is to name both classes when setting the properties
.class1, .class2 {text-indent: 100}
.class2{/*extra properties here*/}
You can define 2 classes in this way
.class1, .class2 { text-indent: 100 }
And it will work for you
Moreover if you want to ad some more in class2 then you can define it
.class2 { /*whatever you want here*/ }
Others mentioned SASS and LESS. Here's the solution of Stylus:
.class1
text-indent: 100
.class2
#extend .class1

Avoid classes only used internally from being produced in generated CSS

Say I have the following LESS:
#accent: #00aa22;
.mainStyle
{
border-radius:0.5em;
border: 1px solid #accent;
}
#someElement
{
.mainStyle;
}
I only ever use .mainStyle in my LESS, and never actually use it in my HTML for any elements. It's just being used to avoid repetition inside my LESS file.
In the generated CSS however, .mainStyle is redundant, since it's only used within my LESS.
Is there a way to exclude that class from the generated CSS while using it within the LESS?
Got this 20 seconds after asking the question...
You can make the class a parameterless mixin by adding brackets to the end:
.mainStyle()
{ ... }
Now its contents only appear where it's used in your LESS and never as a class in its own right in the generated CSS.