I have couple of partials(say _one.scss and _two.scss) which am calling into a SASS. _one.scss has following code
#mixin wire($num) {
.parts-field {
height: 100%;
width: calc(100% * (1/$num) - 10px - 1px);
}
And in _two.scss has
.mytry {
#include wire(3);
}
In my main.scss am doing the following
#import "../../base/_one.scss";
#import "_two.scss";
When I check main.css, it shows the following:
.mytry .parts{
height: 100%;
width: calc(100% * (1/$num) - 10px - 1px);
}
Even though am saying #include wire(3), I believe the 3 is not getting passed. Styles are not applying on the HTML either. Is there something fundamentally wrong am doing with param passing to mixins?
You need to use string interpolation, i.e. replace $num with #{$num}:
#mixin wire($num) {
.parts-field {
height: 100%;
width: calc(100% * (1/#{$num}) - 10px - 1px);
}
}
The reason why this is needed because SASS will treat (...) as a calculation that has to be evaluated during compilation, and it does not know that calc(...) should be interpreted as a string and not a mathematical expression.
Related
I'm just curious to know if it is possible to have specific stylings based on the name of of a class.
For example, Bootstrap 4 has a helper class for margins and padding like:
<div class="m-t-1 p-a-0"></div>
This gives the div 1em of margin to the top, and removes padding from all sides.
I am sure they have pre-styled this class in their CSS to achieve this.
But I am curious if there is a way to use the class as a variable.
for example:
<div class="fs-x"></div>
where x can be any number, this class would then give the styling the font-size: x to the div.
Is this possible to do?
Thanks.
You can use a CSS pre-processor such as SASS or LESS to achieve this however it generates static classes within a specified range below is an example from the SASS documentation:
$class-slug: for !default
#for $i from 1 through 4
.#{$class-slug}-#{$i}
width: 60px + $i
Which emits this CSS:
.for-1 {
width: 61px;
}
.for-2 {
width: 62px;
}
.for-3 {
width: 63px;
}
.for-4 {
width: 64px;
}
All CSS classes must be explicitly defined. So every variation if X would need to exist in a .css file
you can use constant in css for example
$x = 10px;
img{
margin-bottom : $x;
}
but however you can declare variables with this way
:root {
--color-principal: #06c;
}
#foo h1 {
color: var(--color-principal);
}
This code:
index.htm.twig
<div id="myBar">Hello</div>
<div id="myDiv">{VERY_LONG_LOREM_IPSUM}</div>
pure style.css
#myBar {
height: 40px;
}
#myDiv {
height: calc(100% - 40px); // document height - #myBar height
}
Everything is OK here.
But when I change pure style.css to style.less:
style.less
#myBar {
height: 40px;
}
#myDiv {
height: calc(100% - 40px); // document height - #myBar height
}
The function calc(100% - 40px); is compiled to calc(60%); in style.css.
I expected the same value like in pure style.css file.
How to fix this issue?
LESS Documentation - String Functions - Escaping
CSS escaping, replaced with ~"value" syntax.
When you're using LESS, you need to escape it, otherwise the numbers will be evaluated, as you are seeing. In this case, you would use calc(~"100% - 40px"):
#myDiv {
height: calc(~"100% - 40px");
}
Suppose I have two virtually identical HTML structures, but with different class names. They only differ by a few variables, like width and height. By using SASS/SCSS variables I thought I could do something like this:
.widget-a {
$width: 50px;
}
.widget-b {
$width: 100px;
}
.widget-a,
.widget-b {
button {
background: red;
width: $width;
}
}
This would let me write a single piece of SASS nested code for both widgets a and b. However, variables are only visible inside a nested scope, so SASS returns 'variable undefined' errors. Of course I could rewrite it by simply doing something like:
.widget-a,
.widget-b {
button {
background: red;
}
}
.widget-a {
button {
width: 50px;
}
}
.widget-b {
button {
width: 100px;
}
}
But that seems pretty cumbersome. Is there any other method of making this work?
Variables in SASS are only scoped to the block they appear in. Your first .widget-a declaration and the one declaring both A and B are two separate scopes. You'll have to do something like this (assuming you need to use the widths more than once):
$wbackground: red;
.widget-a {
$wawidth: 50px; /* widget A width */
button {
background: $wbackground;
width: $wawidth;
}
}
.widget-b {
$wbwidth: 100px; /* widget B width */
button {
background: $wbackground;
width: $wbwidth;
}
}
Ran into the same problem, this is how I'm going to try to solve it... (this works)
#mixin foo($type:"default")
.mClass
$bg: inherit
#if $type == "banana"
$bg: yellow
background: $bg
.firstClass
#include foo
.secondClass
#include foo("banana")
Your problem can be solved by using a mixin.
#mixin button($width){
button{
background:red;
width:$width;
}
}
.widget-a{ #include button(50px); }
.widget-b{ #include button(100px); }
I don't see the advantage of creating a mixin only for this specific situation, it is hardly useful on a couple of occasions, but it is just my opinion.
Anyway, I've created a mixin, just for fun. I think that it can help you to deal with this specific situation. Here is the mixin and I'm going to try to explain how it works:
#include button($selectors, $property, $values, $child: false) {
// Common properties that are included in all $selectors
}
This mixin takes four parameters:
$selectors: List of selectors, in your case, .widget-a and .widget-b, they should be enclosed in quotes.
$property: Here you should enter the name of the property, in your case width
$values: Values are, as the name implies , the values of the property for each selector
$child: Here you can enter the name of a child, this is optional.
Into the brackets {} you should write all the properties that you want to include in all $parameters
The order of each selector must match the order of their corresponding value
So, here's an example using this mixin to solve your problem. This is the #include:
#include (".widget-a" ".widget-b", width, 50px 100px, button) {
background: red;
}
And this, the code that returns:
.widget-a button, .widget-b button {
background: red; }
.widget-a button {
width: 50px; }
.widget-b button {
width: 100px; }
This is another way to achieve the same result:
#include button(".widget-a .button" ".widget-b .button", width, 50px 100px) {
background: red;
}
Download the mixin here
I'm trying to use http://startbootstrap.com/stylish-portfolio in my rails app however I'm getting the following error in my stylish-portfolio.css.scss.erb file:
ActionView::Template::Error (Invalid CSS after "body ": expected selector or at-rule, was "{"
This is my css file:
#import 'bootstrap'
/* Global Styles */
html,
body {
height: 100%;
width: 100%;
}
.vert-text {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.vert-text h1 {
padding: 0;
margin: 0;
font-size: 4.5em;
font-weight: 700;
}
...
My guess is that you are missing a semicolon in the stylish-portfolio.css.scss.erb file, maybe after an SCSS variable definition?
Here's the original CSS file I assume you are basing this on, maybe you want to do a diff between that and yours to determine what has changed.
Edit: Yup, apparently there is a missing semicolon after the first line. The #import statement
#import 'bootstrap'
should instead be
#import 'bootstrap';
since you are using the .scss extension. You can omit the semi-colon if you are using the .sass extension.
I am trying to do something like this:
.my-style {
width: 50px;
margin-left: calc(50% - calc(width / 2));
}
Later I am changing the width to 90px and I want the margin grow accordingly.
It doesn't work. Is it possible?
The newest browser's SHOULD support it, I tried the following code.
This is a webkit example I made, so check it in chrome
CSS
p {
-webkit-var-a: -webkit-calc(1px + 3px);
margin-left:-webkit-calc(-webkit-var(a) + 5px);
}
HTML
<p>This text should have margin-left, but it doesn't</p>
FIDDLE
http://jsfiddle.net/uqE8b/
If you inspect the <p> element you can see that it DOES see the code as valid, it just doesn't do anything... So it seems that for now you have to use javascript, LESS or anything equivelent as it's still a experimental feature.
EDIT:
it DOES seem to work when you make the var a plain number:
p {
-webkit-var-a: 3px;
margin-left:-webkit-calc(-webkit-var(a) + 5px);
}
http://jsfiddle.net/uqE8b/1/
So to answer your question, yes this is possible, but I would not recommend it for now.
CSS
.my-style {
height:100px;
background-color:black;
-webkit-var-width: 50px;
margin-left: -webkit-calc(50% - -webkit-var(width) / 2);
}
FIDDLE
http://jsfiddle.net/ShsmX/
You can't do something like that with standard CSS, you should investigate an alternative such as LESS
Edit: I was wrong, CSS3 supports this if you use var() within calc():
.my-style {
width: 50px;
margin-left: calc(50% - (var(width) / 2));
}
I think should do it.
.my-style {
width: 50px;
margin-left: calc(100% - calc(width / 2));
}
Try like this, it worked wonder for me.