I'm looking for a way to do something like this:
// style.css
#def borderSize '2px';
.style {
width: borderSize + 2;
height: borderSize + 2;
}
where the width and height attributes would end up having values of 4px.
Sometimes I use the following:
#eval BORDER_SIZE_PLUS_2 2+2+"px"; /* GWT evaluates this at compile time! */
Oddly, this only works, if you don't put any spaces between the + operator and the operands. Also, in #eval you can't use constants that were previously defined by #def. You can however use constants that are defined as static fields in one of your Java classes:
#eval BORDER_SIZE_PLUS_2 com.example.MyCssConstants.BORDER_SIZE+2+"px";
Or you could let the calculation be performed completely by Java:
#eval WIDTH com.example.MyCssCalculations.width(); /* static function,
no parameters! */
#eval HEIGHT com.example.MyCssCalculations.height();
.style {
width: WIDTH;
height: HEIGHT;
}
But what I would actually like to do is very similar to your suggestion:
#def BORDER_SIZE 2;
.style {
width: value(BORDER_SIZE + 2, 'px'); /* not possible */
height: value(BORDER_SIZE + 3, 'px');
}
I don't think that's possible in GWT 2.0. Maybe you find a better solution - here's the Dev Guide page on this topic.
Mozilla kind-of-sort-of-not-really supports this with it's CSS calc() function.
This example shamelessly stolen (with attribution!) from Ajaxian
/*
* Two divs aligned, split up by a 1em margin
*/
#a {
width:75%;
margin-right: 1em;
}
#b {
width: -moz-calc(25% - 1em);
}
It's not cross-browser, and it's probably only barely supported by even bleeding-edge versions of Firefox, but there's at least being progress made in that direction.
You could also calculate in your provider method, if you put a parameter in the function:
#eval baseFontSize com.myexample.CssSettingsProvider.getBaseFontSize(0)+"pt";
#eval baseFontSize_plus_1 com.myexample.CssSettingsProvider.getBaseFontSize(1)+"pt";
com.myexample.CssSettingsProvider would look like this:
public static int getBaseFontSize(int sizeToAdd) {
if (true) {
return 9 + sizeToAdd;
}
return baseFontSize;
}
I would also love somehting like that, but it's not possible.
Even in CSS 3 their is nothing planned like this.
If you really want to make something like that, one possibility is to use
php and configure your webserver, so that .css files are parsed by php.
So you could do something like
<?
$borderSize = 2;
?>
.style {
width: <? borderSize+2 ?>px;
height: <? borderSize+2 ?>px;
}
But as this is no 'standard' way, i think its better to not do it.
Related
I want to create custom css unit, that I'll be able to use in sass with node.js. Is there any guide about creating sass plugin for this? Just for example, I want to create unit "dpx", that will work as double pixel, so "width: 20dpx" will be processed to "width: 40px".
Other solution (not sass plugin), that can work with node is also acceptable.
Use a SASS function that accepts a font-size and returns the value doubled.
#function dpx($size) {
#return $size * 2;
}
div {
font-size: dpx(20px); // output: font-size: 40px;
}
As a simplified version of the current answer, you could also write the following:
$d: 2px;
div { font-size: 20*$d; }
I know this is an old question, but since I found it, other people will find it too.
In such case as yours a good solution would be to make a 1rem equal to 2px.
You can do it this way:
html {
font-size: 2px;
}
now each 1rem will be equal to 2px. If you want to make sure this doesn't break your current page, you can always add
body {
font-size: 8rem;
}
to set the global font-size to 16px (just a guess since this is a default value).
I'm trying to build my own tiny scalable grid in CSS / scss.
So far I found this decision:
:root {
--page-width: 1170px;
--gutter: 15px;
--columns: 12;
}
.wrapper {
max-width: var(--page-width);
margin-right: auto;
margin-left: auto;
padding-left: var(--gutter);
padding-right: var(--gutter);
}
.row {
margin-left: calc(-1 * var(--gutter));
margin-right: calc(-1 * var(--gutter));
}
.col {
display: block;
margin-left: var(--gutter);
margin-right: var(--gutter);
}
Then I tried to use scss to shorten columns classes description (which at the same time will allow me to change number of columns in one single place in whole code - in CSS Variable --columns) like this
#for $n from 1 through var(--columns) {
.col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); }
}
but it didn't work. The interesting detail is that when I change #for statement from #for $n from 1 throughvar(--columns)`` to #for $n from 1 through12 it compiles well. And there is no problem in compiling CSS-Variable inside #for body. .col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); } compiles well into needed series of classes.
If I use scss variable $columns instead of CSS variable then I'll need to import my grid.scss file into all other scss files of the project.
It's my first question on StackOverflow, so let me know if any other details are needed.
CSS and SCSS variables are two very different things (please see this pen)
To make it work you need a static variable for SCSS to compile
// static (SCSS) variables used produce CSS output
$page-width: 1170px;
$gutter : 15px
$columns: 12;
// dynamic (CSS) variables used at run-time
// note the values are interpolated
:root {
--page-width: #{$page-width};
--gutter : #{$gutter};
--columns: #{$columns};
}
// the for loop is aimed at producing CSS output
// ... why you need the static variable
#for $n from 1 through $columns {
// the content becomes CSS output
// ... why you can use dynamic variables
.col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); }
}
You need to use interpolation (eg. #{$var}) on your variable in order for Sass to treat it as a CSS property. Without it, you're just performing variable assignment.
#mixin w_fluid($property_name, $w_element, $w_parent:16) {
#{$property_name}: percentage(($w_element / $w_parent));
}
The accepted answer is no longer valid. Newer versions of SASS require interpolation to be used for variables.
Refer here for more details
$accent-color: #fbbc04;
:root {
// WRONG, will not work in recent Sass versions.
--accent-color-wrong: $accent-color;
// RIGHT, will work in all Sass versions.
--accent-color-right: #{$accent-color};
}
Is there any way to customize the variables in SASS?
For example:
.m-b-{$number} {
margin-bottom: $number;
}
If I give class="m-b-50" to an element, it should take margin-bottom 50. I just want to know if it is possible with SASS.
Yes it is possible with the help of variable interpolation or variable substitution which uses #{} for variable substitution in SASS and mixins which is a block of code just like function.
Interpolation is the process of evaluating an expression or a string containing one or more variables, yielding a result in which the variables are replaced with their corresponding values.
Simple example of interpolation and set values to the css property in SASS:
$number:60;
$n: 20px;
.m-b-#{$number}{
margin-bottom: #{$number}px;
margin-top: $n;
}
To create customize class names, will use mixins:
#mixin margin-class($side, $number) {
$firstLetter: str-slice($side, 0, 1);
.m-#{$firstLetter}-#{$number}{
margin-#{$side}: #{$number}px;
}
}
$margins: (10, 20);
$sides: ("top", "right", "bottom", "left");
#mixin generate-margin(){
#each $margin in $margins{
#each $side in $sides{
#include margin-class($side, $margin);
}
}
}
#include generate-margin();
Here, generate-margin() will get executed which will call margin-class() for each $margins and $sides, and will generate the below CSS classes:
.m-t-10 {
margin-top: 10px;
}
.m-r-10 {
margin-right: 10px;
}
.m-b-10 {
margin-bottom: 10px;
}
.m-l-10 {
margin-left: 10px;
}
.m-t-20 {
margin-top: 20px;
}
.m-r-20 {
margin-right: 20px;
}
.m-b-20 {
margin-bottom: 20px;
}
.m-l-20 {
margin-left: 20px;
}
That's the one way when you want only for specific values, but if you want to create margin class for 0-20, you can loop thru 0 to 20 as shown below:
#mixin generate-margin(){
#for $margin from 1 through 20{
#each $side in $sides{
#include margin-class($side, $margin);
}
}
}
For anyone else facing this issue, here is how one can achieve this:-
#for $i from 1 through 10 {
.mb-#{$i} {
margin-bottom: #{$i}rem;
}
}
The answer is: no it is not possible. SASS is just a language to pre-generate CSS for you. There is no on-demand, dynamic creation of classes triggered by the contents of your HTML markup. When it comes time for the browser to render your HTML and apply your specified classes, it is still just using CSS. I.e. if you assign class="m-b-50" to an element, the class .m-b-50 must already be explicitly defined somewhere. As noted in the other answers, SASS can make it easier to generate a bunch of pre-defined classes but you must know which values you want to support up front.
Now, you could generate classes for some very large, all-inclusive range like -1000 to 1000 to effectively support all values you might ever try to use and it would seem to do what you wanted, but you would be forcing your users to download a larger CSS file with, most likely, a large percentage of it being unused CSS which is wasteful and can be inconsiderate in a world of paid & limited data plans.
Unfortunately I'm having to go back through my CSS and re-write some styling to make sure it works for IE8 (client needs it). I have a function that adds z-index to elements,
.mobile-pane {
....
....
/* won't work for IE8 */
/* #for $i from 1 through 4 {
&:nth-child(#{$i}) {
z-index: #{$i};
}
} */
&:first-child {
z-index: 1;
& + .mobile-pane {
z-index: 2;
& + .mobile-pane {
z-index: 3;
& + .mobile-pane {
z-index: 4;
}
}
}
}
}
As you can see, the function is clearly commented out. However (I'm using CompileSASS for Visual Studio), in the output window, I see this:
CompileSass 8:35:55 AM:Sass compilation failed for main.
Error: C:/projectFolder/source/sass/components/header:219: unbound variable $i
In Google WebDev, I'm seeing the function's output, ....:nth-child(2) { z-index:2; } ... and so on, not
.mobile-pane:first-child+.mobile-pane {
z-index: 2;
}
, as I would expect. I'm some-what new to SCSS, so I don't know if this is a known problem, or if CompileSass is not reading the comments correctly.
I understand that I could leave the function in, and just have the IE8 z-index CSS below it, and it will still work, but I wanted to leave the function, in case in the future IE8 was no longer a requirement.
My question - is it normal for SCSS to do this, or is it the extension?
Accessing variables within CSS comments is expected, declaring variables within comments is not.
$i: 100;
/* commenting about #{$i} */
Output:
/* commenting about 100 */
Meanwhile:
/*
$j: 100;
commenting about #{$j} */
Raises an error:
Undefined variable: "$j".
If you want to comment out blocks of code that access variables that don't exist due to being commented out, use double slashes instead:
$j: 100;
.foo {
// content: $j;
}
I have implemented a fluid layout with Semantic.gs and some nested columns with LESS. But now our client decided they want the layout to be fixed.
I thought I could simply comment out the line #total-width:100% in grid.less, however now the other LESS files give an error on lines with the .row() mixin.
Is there a workaround for this?
Here is the relevant portion of grid.less
/////////////////
// Semantic.gs // for LESS: http://lesscss.org/
/////////////////
// Defaults which you can freely override
#column-width: 20;
#gutter-width: 10;
#columns: 47;
// Utility variable - you should never need to modify this
#gridsystem-width: (#column-width*#columns) + (#gutter-width*#columns) * 1px;
// Set #total-width to 100% for a fluid layout
//#total-width: #gridsystem-width;
//#total-width: 100%;
// Uncomment these two lines and the star-hack width/margin lines below to enable sub-pixel fix for IE6 & 7. See http://tylertate.com/blog/2012/01/05/subpixel-rounding.html
#min-width: 980;
#correction: 1 / #min-width * 100 * 1.5%;
Here is the problematic section of the LESS file. The LESS compiler gives the error 'Compiler Errors
variable #total-width is undefined (Line: 292)', which is the line with the .row() attribute:
#v_main_wrapper{
position:relative;
float:none;
.row(47);
&:after{
content: "";
display: table;
clear: both;
}
}
I would think that you would want this:
#total-width: #gridsystem-width; //leave this uncommented, to calculate width
//#total-width: 100%;