Error when minifying CSS with #keyframes - asp.net-mvc-4

I'm using the default bundling and minification in MVC 4.
One of our stylesheets starts with this bit of CSS:
#media (max-width: 979px) {
#keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
#-webkit-keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
}
The minification fails with this error: run-time error CSS1019: Unexpected token, found '}' and it points to the first character on line 13 (that's the very last } in the snippet above).
I'm not overly familiar with CSS in general and I was wondering:
Is that valid CSS? It fails validation at
https://jigsaw.w3.org/css-validator/validator
What changes are needed to get the file minified? There are about 300 lines in the file so I would really like to get it minified if possible.

#keyframes declarations must be outside media queries.
#keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
And then you use them in the media query like this:
#media (max-width: 979px) {
.some-class {
animation: sidebarSlideInRight 1s;
}
}

To add to #Flower's answer:
If you need the animation to work differently based on a media query, make multiple keyframes with different names. Then in the media query use the animation-name for the needed keyframe.
#keyframes sidebarSlideInRight-1 {
from { right: -220px }
to { right: 0 }
}
#keyframes sidebarSlideInRight-2 {
from { right: -250px }
to { right: 50 }
}
#media (max-width: 768px) {
.some-class {
animation: sidebarSlideInRight-1 1s;
}
}
#media (max-width: 979px) {
.some-class {
animation: sidebarSlideInRight-2 1s;
}
}
Like #Flower said, just make sure the keyframes are not in the media query.

Related

Change mixin variable based on media (or some other condition)

Say I have a complex mixin function. Something like
.MyMixin(#Count, #ManyOtherVars)
{
.Item
{
width: calc( 100% / #Count);
}
//lot's of other rules not affected by #Count
}
And then I want to call this mixin with different values for different media
e.g.
.SomeClass
{
#media screen (max-width: 1000px)
{
.MyMixin(5, 1);
}
#media screen (min-width: 1000px)
{
.MyMixin(10, 1);
}
}
This works fine, except the generated css duplicates all the stuff which has not changed
#media screen (max-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 5 );
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
}
#media screen (min-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 10 );
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
}
Which, needless to say, is quite wasteful when only one thing changed.
Are there any workarounds to produce a leaner output that don't require the calling class to know something about what the mixin does, or for the mixin to know about media rules?
I thought maybe a detached rule-set could help, but given variables are not exported from those I'm not sure how it would.
Desired output:
#media screen (max-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 5 );
}
}
#media screen (min-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 10 );
}
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
Remove static styles from your mixin and place them directly to SomeClass selector.
.SomeClass {
// Lot's of other rules not affected by #Count
#media screen (max-width: 1000px) {
.MyMixin(5, 1);
}
#media screen (min-width: 1000px) {
.MyMixin(10, 1);
}
}
Better solution:
.MyMixin(#Count, #ManyOtherVars) {
width: calc( 100% / #Count);
}
.SomeClass {
// Lot's of other rules not affected by #Count
.Item {
#media screen (max-width: 1000px) {
.MyMixin(5, 1);
}
#media screen (min-width: 1000px) {
.MyMixin(10, 1);
}
}
}
Now mixin does only one thing. It's simple and reusable.

Set "min-width" or "max-width" in a media query passing a parameter to a mixin

I would like to make dynamic MIN/MAX suffix in properties defined in a Less MediaQuery.
I wrote this code but it does not compile:
#screen-md: 800px;
.MEDIAQUERY(#min-max, #size)
{
#media screen and (#{min-max}-width: #size)
{
#{min-max}-width:100px;
}
}
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
While #{min-max}-width:100px; is a correct syntax, equivalent applied in Mediaquery definition is not allowed, but I need to set sometime "max-width" value, and others "min-width" value in my media queries. How to obtain this?
Option 1: (Using a variable and interpolation)
You can do it like below
.MEDIAQUERY(#min-max, #size) {
#mediaQuery: ~"screen and (#{min-max}-width: #{size})";
#media #mediaQuery {
#{min-max}-width:100px;
}
}
Option 2: (Using Guards)
You can use guards in the mixin like below to check what was the value that was passed for the #min-max parameter and then output the appropriate CSS based on it.
.MEDIAQUERY(#min-max, #size){
& when (#min-max = min) {
#media screen and (min-width: #size) {
min-width:100px;
}
}
& when (#min-max = max) {
#media screen and (max-width: #size) {
max-width:100px;
}
}
}
When the above mixin is called like below (with either of the options mentioned above):
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
div{
background-color: red;
.MEDIAQUERY ( #min-max: min, #size: #screen-md );
}
it would compile into the below CSS:
header {
background-color: blue;
}
#media screen and (max-width: 800px) {
header {
max-width: 100px;
}
}
div {
background-color: red;
}
#media screen and (min-width: 800px) {
div {
min-width: 100px;
}
}

How to declare same style for #media and descendant selector?

I need to define same style for elements under a media query and descendant by another class.
Perfect solution in LESS could be the following [pseudo-code]:
.foo
{
color:red;
.example &,
#media (min-width:800px)
{
color:blue;
}
}
that should be desirable that would be compiled into:
.foo {
color: red;
}
.example .foo {
color: blue;
}
#media (min-width: 800px) {
.foo {
color: blue;
}
}
THIS SYNTAX IS INCORRECT but, do you have some suggestion to solve my problem?
Nope, selectors and #media queries are too different language entities (despite having similar {} syntax) so you can't combine those with comma like in your example.
So to get it DRY (assuming that shared style has more than one property of course) you'll need a mixin (or sort of), for example:
.foo {
color: red;
.somename() {
color: blue;
}
.example & {.somename}
#media (min-width: 800px) {.somename}
}
Also see Passing Rulesets to Mixins examples (if you need even more generic solution).
Thanks to #seven-phases-max suggestion, I finally found a possible solution using Detached Ruleset:
#screen-xs: 480px;
#screen-sm: 769px;
#screen-md: 992px;
#screen-lg: 1200px;
.MEDIAQUERY(#only-media, #min-max, #size, #RULES)
{
#screen-width:~"#{screen-#{size}}";
#mediaQuery: ~"screen and (#{min-max}-width: #{screen-width})";
#media #mediaQuery { #RULES(); }
& when (#only-media = false) {
.#{size} & { #RULES(); }
}
}
.foo_media-and-class
{
color:red;
.MEDIAQUERY(#only-media:false, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:false, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
.foo_only-media
{
color:red;
.MEDIAQUERY(#only-media:true, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:true, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
This solution go beyond and offer other options:
Possibility to set a custom value of screen width for media query,
Pass MIN/MAX value of property used in media query (Try to pass "max" instead of "min" calling .MEDIAQUERY mixin)
Toggling generation of simple media query or media query + descendant selector, through #only-media boolean.
I think your comma might be causing the error.
.foo {
color:red;
.example & {
color:blue;
#media (min-width:800px) {
color:blue;
}
}
}
This is proper syntax to output the following:
.foo {
color: red;
}
.example .foo {
color:blue;
}
#media (min-width:800px) {
.example .foo {
color:blue;
}
}

Does LESS have something comparable to the #content directive in Sass?

I tried to convert a more "advance" mixin from SASS to LESS but unsuccessful.
Here is the mixin:
.breakpoint(#point) {
#if #point == really big{
#media (max-width: 80em) { #content; }
}
#if #point == mid {
#media (max-width: 60em) { #content; }
}
#if #point == small {
#media (max-width: 42em) { #content; }
}
}
and another one, I didn't touch this one:
#mixin keyframes( $animationName )
{
#-webkit-keyframes $animationName {
#content;
}
#-moz-keyframes $animationName {
#content;
}
#-o-keyframes $animationName {
#content;
}
#keyframes $animationName {
#content;
}
}
update
I did not check the sample code provide by #Harry in the comments, before answering this question. This sample code provide a good a clean way to solve your question too. Please also see: http://codepen.io/hari_shanx/pen/ayIej
First notice that Less do not support if / else constructs (alhought mixins libraries such as https://github.com/pixelass/more-or-less adds .if() (if - then - [else]) ), but uses guards to create conditional mixins, also see: http://lesscss.org/features/#mixin-guards-feature
or alternatively consider http://lesscss.org/features/#mixins-parametric-feature-pattern-matching
Your mixins also use the #content; which you call the #content directive, i think you should compare this with "Passing Rulesets to Mixins", see: http://lesscss.org/features/#detached-rulesets-feature.
Your first mixin using pattern-matching:
.breakpoint(reallybig;#content)
{
#media (max-width: 80em) { #content(); }
}
.breakpoint(mid;#ruleset)
{
#media (max-width: 80em) { #content(); }
}
example caller:
.breakpoint(reallybig; {p{color:red;}});
Your first mixins leveraging guards:
.breakpoint(#size;#content) when (#size = 'really big')
{
#media (max-width: 80em) { #content(); }
}
.breakpoint(mid;#ruleset) when (default())
{
#media (max-width: 80em) { #content(); }
}
.breakpoint('really big'; {p{color:red;}});
And your second mixin:
.keyframes(#animationName;#animation)
{
#-webkit-keyframes #animationName {
#animation();
}
#-moz-keyframes #animationName {
#animation();
}
#-o-keyframes #animationName {
#animation();
}
#keyframes #animationName {
#animation();
}
}
#animation: {0% {
left: 0;
transform: translate(10px, 20px);
}
100% {
left: 100%;
transform: translate(100px, 200px);
}};
.keyframes(test;#animation);

Bootstrap, pull-left for small devices

I'm building a site in Bootstrap 3.
Is there anyway to make a element use the class pull-left on smaller devices and use pull-right on larger ones?
Something like: pull-left-sm pull-right-lg.
I've managed to do it with jquery, catching the resize of the window. Is there any other way? Pref without duplicating the code in a hidden-x pull-left. Or is it considered more ok to duplicate code/content now when going responsive?
Just add this to your SASS file:
#media (max-width: $screen-xs-max) {
.pull-xs-left {
float: left;
}
.pull-xs-right {
float: right;
}
}
#media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
.pull-sm-left {
float: left;
}
.pull-sm-right {
float: right;
}
}
#media (min-width: $screen-md-min) and (max-width: $screen-md-max) {
.pull-md-left {
float: left;
}
.pull-md-right {
float: right;
}
}
#media (min-width: $screen-lg-min) {
.pull-lg-left {
float: left;
}
.pull-lg-right {
float: right;
}
}
Insert actual px values for $screen-* if you use plain CSS of course.
HTML:
<div class="pull-md-left pull-lg-left">
this div is only floated on screen-md and screen-lg
</div>
You can use CSS Media Queries
basic usage will be like this; if you want to float left below devices of width 500px, then
#media (max-width: 500px) {
.your_class {
float: left;
}
}
#media (min-width: 501px) {
.your_class {
float: right;
}
}
There is no need to create your own class with media queries. Bootstrap 3 already has float ordering for media breakpoints under Column Ordering.
The syntax for the class is col-<#grid-size>-(push|pull)-<#cols> where <#grid-size> is xs, sm, md or lg and <#cols> is how far you want the column to move for that grid size. Push or pull is left or right of course.
I use it all the time so I know it works well.
Possibly you can use column ordering.
<div class="row">
<div class="col-md-9 col-md-push-3">.col-md-9 .col-md-push-3</div>
<div class="col-md-3 col-md-pull-9">.col-md-3 .col-md-pull-9</div>
</div>
Looks like floating columns will be getting added to version 4 by like #Alex has done - https://github.com/twbs/bootstrap/issues/13690
Yes. Create your own style. I don’t know what element you’re trying to float left/right, but create an application.css file and create a CSS class for it:
/* default, mobile-first styles */
.logo {
float: left;
}
/* tablets and upwards */
#media (min-width: 768px) {
.logo {
float: right;
}
}
Don’t be afraid to write custom CSS. Bootstrap is meant to be exactly that: a bootstrap, a starter point.
This is what i am using . change #screen-xs-max for other sizes
/* Pull left in mobile resolutions */
#media (max-width: #screen-xs-max) {
.pull-xs-right {
float: right !important;
}
.pull-xs-left {
float: left !important;
}
.radio-inline.pull-xs-left + .radio-inline.pull-xs-left ,
.checkbox-inline.pull-xs-left + .checkbox-inline.pull-xs-left {
margin-left: 0;
}
.radio-inline.pull-xs-left, .checkbox-inline.pull-xs-left{
margin-right: 10px;
}
}
LESS version of #Alex's answer
#media (max-width: #screen-xs-max) {
.pull-xs-left {
.pull-left();
}
.pull-xs-right {
.pull-right();
}
}
#media (min-width: #screen-sm-min) and (max-width: #screen-sm-max) {
.pull-sm-left {
.pull-left();
}
.pull-sm-right {
.pull-right();
}
}
#media (min-width: #screen-md-min) and (max-width: #screen-md-max) {
.pull-md-left {
.pull-left();
}
.pull-md-right {
.pull-right();
}
}
#media (min-width: #screen-lg-min) {
.pull-lg-left {
.pull-left();
}
.pull-lg-right {
.pull-right();
}
}