css components and responsive coupling - best practices? - css

Say I create a component like a table that I wish to reuse across different pages. The content and number of columns in the table will vary from page to page, but the look and feel should be the same.
.my-table {
background-color: ... etc
color: ... etc
}
When making this component responsive - should each page have it's own set of media queries that alters the look of this component, or should the component itself define the queries?
Ie. I may want to hide columns 3 and 5 of this table when viewing on mobile, but on another page there may only be 3 columns and I don't want column 3 to be hidden on that page. What is the better practice to use in this case? Should the responsive logic be decoupled from the component styles?
Another example - most css guides i've read recommend doing something like this:
.layout-columns-2 {
float: left;
width: 50%;
}
.layout-columns-4 {
float: left;
width: 25%;
}
Which you can reuse on layouts whenever you need columns to float side by side. But again you run into similar issues the moment you try applying responsive rules.
Say for example on one page, you want to break the float of a particular div when the width is 600px so that the columns are stacked vertically. But on another section of the page, you want the float to break at 800px. What is the best approach to this?

I'd suggest creating a Sass partial with some table mixins, which can be applied as needed. This will let you decouple your table "modules" from your actual tables. Decoupling is usually a good thing, as it lets you add and change styles with greater ease and consistency.
Since you want your breakpoints to vary from table to table, I would leave the table styles as "mobile-first" by default, and customize them one-by-one as appropriate.
_tables.scss:
table {
// Global, mobile-first styles go here
}
#mixin columns-2() {
td {
float: left;
width: 50%;
}
}
#mixin columns-4() {
td {
float: left;
width: 25%;
}
}
// Function to return a max breakpoint (1px less)
#function max-break($size) {
#return $size - .0625em;
}
Using your partial, you can apply your mixins as appropriate for any specific table ...
special-page.scss:
#import 'tables';
.my-table {
// Hide columns 2/4 below 800px
#media (max-width: max-break(50em)) {
td:nth-child(2),
td:nth-child(4) {
display: none;
}
}
// Use 2 columns at 600px
#media (min-width: 37.5em) {
#include columns-2();
}
// Use 4 columns at 600px
#media (min-width: 50em) {
#include columns-4();
}
}

Related

Less mixins, variable colours specificity

I have a design where I need to be able to change colours on a page depending on the input in the cms.
To do this I'm adding one class to a containing div and I'll change the colours according to that surrounding class.
There's going to be a set amount of colours. (8, I think. It's not been decided yet.)
My idea was to use a mixin to accomplish this. eg.
Example HTML
<div class="color-1>
<h1 class="h1">My Title</h1>
</div>
Example LESS Mixin
.color() {
#color_1: red;
.color-1 & {
color: #color_1;
}
#color_2: blue;
.color-2 & {
color: #color_2;
}
//etc.....
//I have a similar mixin for background-color -> .bg-color();
}
Example LESS
.h1 {
.color();
background-color: #fff;
#media screen and (min-width: 960px) {
color: #fff;
.bg-color();
}
}
Problem
The problem is that the specificity for the mobile version is higher than the desktop one.
Example rendered CSS
//Could be color-2, color-3 etc. depending on class, doesn't matter for this example
.color-1 .h1 { //This would override the media query below due to 2 classes
color:red;
}
.h1 {
#media screen and (min-width: 960px) {
color: #fff;
background:color: red;
}
}
This issue will effect the rest of the page. Is there a better way to accomplish what I'm looking for without sticking important tags everywhere?
________________Edit________________
For clarity, the site I'm building will allow logged in users of a certain tier to change the main colour of their personal page, I still need the client to decide on how many colours but I think it will be around 8. Instead of writing out each of those, or having a separate stylesheet for each one (Maintaining that would be horrible) I decided to create a Mixin for it. There will be mutiple background colours and text colours that need to change, and due to the design they will need the change to different colours at mobile desktop and tablet.
Thinking of the nature of CSS something must be amiss with your code as the browser will always take the last value you give to a certain selector.
For example the following h1 would be red:
<h1 class="foo">Headline</h1>
.foo { color: blue; }
.foo { color: red; }
And it will change it's color when you give it a different value inside a mediaquery if the mediaquery is matched. So in the example below the h1 will be green when the viewport exceeds 399px in width:
<h1 class="foo">Headline</h1>
.foo { color: blue; }
.foo { color: red; }
#media all and (min-width: 400px) {
.foo { color: green; }
}
What's confusing me is the difference between your LESS code and what's in the outpout CSS. I'd suggest you have a second look at your selectors and/or variables. Indentation can be quite confusing as well, so may be you should opt for a mobile-first LESS file and then create others for mediaqueries (and import those in a main less file keeping the order intact).

CSS: Is it possible to create a class which only overrides properties within a given media query?

This is my class:
.center-block-xs {
// This style is given to an image. I want the image to keep
// its original CSS (whatever the default display and margin
// is for an image) unless the screen size fits within the
// media query below.
}
#media(max-width:767px) {
.center-block-xs {
display: block;
margin-right: auto;
margin-left: auto;
}
}
Basically, what I want to do is this: If an element has the class .center-block-xs, then the CSS should be applied to the element only if the screen size is within the media query. I know I can do this:
#media(max-width:767px) {
.color-red-xs { color: red; }
}
#media(min-width:768px){
.color-red-xs { color: black; }
}
In which case the color is red only if the screen size is within the media query, otherwise it gets overridden with the black color. But I don't want to have to override any CSS in my case; I just want the CSS to be what it normally would be unless the screen size is within the media query. Is this possible?
What you're describing is precisely how CSS and media queries work by default. If you define a class of .center-block-xs within a media query, that definition will only be applied to elements that a) have that class, when b) the media-query rules apply. There is no need to explicitly define the alternative case(s) if you want inherited styles to be applied.
Just set the default color to what you want, such as the following:
.center-block-xs {
color: red;
}
Then set a minimum width for the CSS change, like so:
#media(min-width: 767px) {
.center-block-xs {
color: black;
}
}
when the screen hits a width of 767px, the text will change.

Media queries in less with variables-need global variables

I am looking for a solution where I define 1 variable globally and than overwrite it inside a media query - without putting the entire code in it (like LESS CSS set variables in media query?).
I thought something like that(defining):
#media (min-width: 768px) {
#BWInputHeight: 40px;
}
#media (max-width: 768px) {
//responsive screens
#BWInputHeight: 20px;
}
And using it like that:
.dataTables_filter input {
.form-control;
max-width: 135px;
display: inline-block;
height: #BWInputHeight;
padding: 1px 6px;
margin-right: 15px;
}
The problem here, "#BWInputHeight" is a undeclared variable. How can I solve this with LESS ?
You can sort of achieve this by using list arrays for each property and screen-width (like the below sample):
#BWInputHeight: '20px','40px','60px'; // Height of the button for min-width=320 and min-width=768 respectively
#minwidths: '320px','768px','1024px'; // The widths for which you need the media queries to be created
.loop-column(#index) when (#index > 0) { // Loop to iterate through each value in #minwidths and form the corresponding output
.loop-column(#index - 1);
#width: extract(#minwidths, #index); // extracts width based on array index
#media (min-width: e(#width)){
.dataTables_filter input{
height: e(extract(#BWInputHeight,#index)); // extracts button height for the corresponding screen width
max-width: 135px;
display: inline-block;
padding: 1px 6px;
margin-right: 15px;
}
}
}
.loop-column(length(#minwidths)); // calling the function
Demo in Code-pen - Modify output area width to see difference and click the eye icon in CSS tab to see compiled CSS.
Note: As per this Stack Overflow thread, both dotless and less.js should be 99% compatible and hence I have given this answer. In case this doesn't work for you, I will happily have this answer removed.

Why do I have to put media queries at the bottom of the stylesheet?

I am new to learning responsive design. What I have noticed on my journey is that when I put media queries at the bottom of the stylesheet, everything works flawlessly in regards to breakpoints. If I put the media queries at the top of the stylesheet, nothing works, and only recently I found out that I need to add !important and max-DEVICE-width ( as opposed to max-width) to the css that is being changed.
Why is this? Why do the media queries work on both desktop and mobile when put at the bottom of the stylesheet.
Why is it that when I put media queries on the top of the stylesheet I need to add !important and also max-DEVICE-width in order for the breakpoints to work on desktop and mobile?
Because css is read from top to bottom. The rule that is set last, is the one that will be executed.
Translating, it is like this:
#media (max-width: 600px) { //If my screen fits this size
.text {
color: red; //Paint it red
}
}
.text {
color: yellow; //Now, forget about everything and paint it yellow!
}
When you add !important is like saying:
#media (max-width: 600px) { //If my screen fits this size
.text {
color: red !important; //Paint it red, and don't change it ever!!!
}
}
.text {
color: yellow; //Ok, I'm not going to paint it yellow....
}
CSS is read from top to bottom.
Everything that is below some other css will overwrite what's on top of it.
It is possible however to use !important at the end of a CSS parameter to make it overwrite everything else
body{
background-color: black !important;
}
body{
background-color: pink;
}
The background-color will be black.
If you remove the !important, it will be pink.
Media queries cascade with the rest of the stylesheet. You can intersperse media queries within your stylesheet, and so you can also cascade styles as needed.
For example:
.my-class {
color: red;
}
.my-class--modifier {
color: blue;
}
#media screen and (min-width: 760px) {
.my-class--modifier {
color: green;
}
}
.some-other-class {
width: 200px;
}
#media screen and (min-width: 760px) {
.some-other-class {
width: 700px;
background-color: gray;
}
.some-other-class .my-class {
border: 2px solid red;
border-radius: 4pt;
}
}
This works precisely due to CSS's cascading nature. You can organize media queries as required based on sections, individual selectors and more.
Basically you are using media queries when you want to apply CSS styles depending on a device's general type (such as print vs. screen), specific characteristics (such as the width of the browser viewport, or environment (such as ambient light conditions).
When you started designing, you generally started doing it for one device of known specifications. So you design it according to you current device and then apply it for other screen sizes.
Hence the order goes like this: Make complete design --> Add the media query to fit for desired screen sizes at the bottom.
It is preferrable to write the query at the bottom became of precedence. That will save you from stress of using important! everytime.

Responsive "list" in two columns

I'm trying to build a list of two types of items, let's call them green and red. In resolutions below 980 I want them stacked in one column, in resolutions above 980 I want them stacked in two columns.
This is what I got so far: http://kristofferk.se/list-test/
(Play around with your browser width to see the one/two column-thing.)
My question: is there an easy way to make the items stack (without the vertical space in between) using just CSS? Not interested in jQuery etc.
Thanks!
you can achieve your results through CSS media queries this is the roughly idea what i am mentioning below:-
#media screen and (max-width: 980px)
{
.class {
background: #ccc;
}
}
read more about media queries :- http://webdesignerwall.com/tutorials/css3-media-queries
UPDATED
just give clear:right to your .in class that vertical space will remove....
.in {
clear: right;
color: green;
float: right;
}
You can write like this:
.in {
clear: right;
color: green;
float: right;
}
.in + .in {
margin-bottom:-30px;
}

Resources