Responsive lists and the nth-child selector - html-lists

I'm having problems understanding nth-child in order to style a list using media queries. I have an unordered list of 6items that displays the items horizontally using display:inline-block; in the following manner:
[item1] [item2] [item3] .... [item6]
ul {
list-style-type: none;
margin-left: auto;
padding:0;
text-align:center;
li {
display:inline-block;
font-size: ms(3);
padding-left: 0.5em;
margin-left: 0.5em;
margin-bottom: 0.2em;
border-left: 1px dotted #d1d1d1;
&:first-child {border:none; margin-left:0;};
a {text-decoration:none;}
}
I'm using foundation 3.2 and Sass, and this unordered list resides inside a div of 12 columns. Ideally, I'd like the list to break-down when the browser width is smaller than 768px as follows:
[item1] [item2] [item3]
[item4] [item5] [item6]
Moreover when the screen is smaller than 320px I'd like the list to display like this:
[item1] [item2]
[item3] [item4]
[item5] [item6]
How can I implement something like this?
Also, I'm using border-left: 1px dotted #d2d2d2 to make a separator between the list items, while having no border for the first item. How can I utilize nth-child so that in the 768 case I don't get the left-border for both the 1st and 4th items? Additionally, in the 320 case how should I implement nth-child so that there is no left-border in items 1,3 and 5

Have you considered using the CSS Columns module? It will do all the math for you (paddings, where the divider appears, etc.). The only problem is that it sorts the items in a different order than what you want.
If you use a column width that is a specific width, it will add/remove columns as necessary for the width of the device without needing media queries.
http://jsfiddle.net/W84Ja/
ul {
padding: 0;
columns: 8em;
column-rule: 1px solid;
column-gap: 2em;
list-style-type: none;
}
If you're looking for a percentage style division, use a specific number of columns combined with media queries.
http://jsfiddle.net/W84Ja/1/
ul {
padding: 0;
columns: 2;
column-rule: 1px solid;
column-gap: 2em;
list-style-type: none;
}
#media (min-width: 25em) {
ul {
columns: 3;
}
}
If you're still set on using inline-block list items, this would be the way to do it:
http://jsfiddle.net/W84Ja/2/
#media (max-width: 20em) {
li:nth-child(even) {
border-left: 1px solid;
}
}
#media (min-width: 20em) and (max-width: 30em) {
li:nth-child(3n+2), li:nth-child(3n+3) {
border-left: 1px solid;
}
}

Related

Render comma separated selectors separately in SCSS

I'm trying to style progress bars using SCSS. To get this working in both Webkit and Gecko browsers I need to use both -webkit and -moz prefixes:
progress {
height: 50px;
-webkit-appearance: none;
appearance: none;
background: cyan;
&::-moz-progress-bar,
&::-webkit-progress-value {
background-color: orange;
}
&::-webkit-progress-bar {
background-color: cyan;
}
}
which renders to
progress {
height: 50px;
-webkit-appearance: none;
appearance: none;
background: cyan;
}
progress::-moz-progress-bar, progress::-webkit-progress-value {
background-color: orange;
}
progress::-webkit-progress-bar {
background-color: cyan;
}
This works great in Firefox, but Chrome doesn't seem to like it. Compare the following two implementations:
Comma separated selectors
progress {
height: 50px;
-webkit-appearance: none;
appearance: none;
background: cyan;
}
progress::-moz-progress-bar, progress::-webkit-progress-value {
background-color: orange;
}
progress::-webkit-progress-bar {
background-color: cyan;
}
<progress max="1" value="0.5"></progress>
Entirely separate declarations
progress {
height: 50px;
-webkit-appearance: none;
appearance: none;
background: cyan;
}
progress::-webkit-progress-value {
background-color: orange;
}
progress::-moz-progress-bar {
background-color: orange;
}
progress::-webkit-progress-bar {
background-color: cyan;
}
<progress max="1" value="0.5"></progress>
The above code snippets render in Firefox and Chrome as shown below
Firefox
Chrome
comma separated
separate declarations
It seems like the problem comes from rendering the CSS with vendor-specific pseudos in comma-separated lists. Is there any way to force the SASS processor to render each selector in a comma separated list as its own declaration?
It would be nice to not use mix-ins, but if it's the only way it's the only way.
Yes, you are able to do so! If you want to render SASS to seperate CSS rules simply divide the comma seperated list into two seperate rules. SASS keeps different rules seperate and will not wrap them together. Example:
// ### > SASS
xprogress {
height: 50px;
appearance: none;
background: cyan;
//## divide comma seperated selectors
//## into different rules
&::-moz-progress-bar {
background-color: orange;
}
&::-webkit-progress-value {
background-color: orange;
}
&::-webkit-progress-bar {
background-color: cyan;
}
}
// ### > compiles to css
progress {
height: 50px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: cyan;
}
//## when compiling CSS
//## different rules will survive
progress::-moz-progress-bar {
background-color: orange;
}
progress::-webkit-progress-value {
background-color: orange;
}
progress::-webkit-progress-bar {
background-color: cyan;
}

Sass get sibling hover state for dropdown menu

I'm trying to build a fairly simple Sass mixin for a dropdown menu built as an html list
My html is
<div class="parent">
<div class="name">My Name</div>
<ul>
<li>profile</li>
<li>logout</li>
</div>
then I have a mixin which is applied to the UL
#mixin dropdown() {
// create a dropdown list from a ul
position: absolute;
display: none;
margin: 0;
padding: 0;
list-style-type: none;
&:hover {
display: block;
}
li {
padding: 0;
background-color: red;
}
li a {
#include button();
padding-left: 0;
}
}
Then I am trying to simply make the css by including the mixin in the parent
.parent {
position: relative;
ul {
#include dropdown();
}
&:hover ul {
display: block;
}
}
The problem is that the mixin needs to set ul { display:block} when I hover on the parent so the css needs to read .parent:hover ul {displa:block} but of course, I'd prefer to have it assigned to the parent rather than add the class on the parent itself.
I thought I should be able to do * &:hover or .parent:hover & or something of that sort, but any combination I've tried has not worked.
Using .parent:hover & creates css of
header .parent ul:hover, .parent:hover header .parent ul {
display: block; }
Which is not right.
Suggestions? Without having to specify the parent element would be preferred.
Originally I was trying to put the mixin no the dropdown itself, but thanks to #cimmanon pointing out that I didn't include how I am using the mixin, I reconsidered the approach and have re-created the mixin to be applied to the parent, which works pretty well, but somebody may have a better way.
.parent {
#include dropdown();
}
#mixin dropdown() {
display: relative;
// create a dropdown list from a ul
&:hover ul {
display: block;
}
ul {
position: absolute;
display: none;
margin: 0;
padding: 0;
list-style-type: none;
&:hover {
display: block;
}
}

Multiple SCSS equations to work out width minus margin

I have a mixin that splits items of a users choosing into an inline-block grid. Users can specify how many in a row, gutter and the child element to target.
This all works fine and an example is below:
Original - SCSS
#mixin list-grid($per-row, $spacing, $selector){
margin: 0 em(-$spacing/2);
#include clearfix;
//negate the display-inline biatch
letter-spacing: -0.31em;
> #{$selector} {
width: 100% / $per-row;
font-size: 16px;
position: relative;
padding: 0 em($spacing/2) em($spacing) em($spacing/2);
display: inline-block;
vertical-align: top;
letter-spacing: 0;
background-clip: content-box;
}
}
My question is.. When i try and use margin I need to rework the calculations as previously this worked because padding is not accounted when working out widths, whereas now with margin I need to adjust the widths to account for the chosen margin.
I'm not sure how to best approach this. Any help appreciated.
New Attempt - SCSS
#mixin list-grid($per-row, $spacing, $selector){
margin: 0 em(-$spacing/2);
#include clearfix;
//negate the display-inline biatch
letter-spacing: -0.31em;
> #{$selector} {
/* not sure what to do here */
width: 100% / $per-row -$spacing;
font-size: 16px;
position: relative;
margin: 0 em($spacing/2) em($spacing) em($spacing/2);
display: inline-block;
vertical-align: top;
letter-spacing: 0;
background-clip: content-box;
}
}
The latest attempt ends up with a width of 8% if I do a row of 3, with 25 gutter. My math must be way off.
Working example

Horizontal list menu: Calculated equal % width

I am very new to sass/compass and I am now experimenting with mixins. The example below shows the code for a simple ribbon style horizontal menu which is already inheriting #include horizontal-list mixin, bundled with compass.
This static menu has four list items and therefore I have set the li width as 25%
My question. Does Compass have a method for calculating an equal percentage width value for the list items in a dynamic menu with an undefined number of items?
Something like, Total li/100 = x% li width
#mixin ribbon-menu {
ul {
padding: 0;
}
li {
width: 25%;
border-right: 1px solid $white;
text-align: center;
}
li.last {
border-left: 0;
}
li.leaf {
padding: 0;
}
a {
display: block;
text-decoration: none;
padding: 10px;
color: $white;
}
a:link, a:visited {
background: $black;
}
a:active, a:hover, a:focus {
background: $red;
}
}
Hopefully this will help you.
http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/
#for $i from 1 through 4 {
li:first-child:nth-last-child(#{$i}),
li:first-child:nth-last-child(#{$i}) ~ li {
width: 100% / $i }
}

Media Query Specificity Image sizing issue at larger viewport using additive css method

I am starting mobile first and adding css as the viewport gets larger, but i've run into an issue with a certain image scaling issue and i can't seem to make sense of it.
I'm using Sass to begin with.
#media 320 i include all my styles for a certain block of content on the page of which I have an image within this block and here is the CSS for this media query:
section.catalog-grid {
position: relative;
height: 100%;
overflow: hidden;
.cat-dvdr {
#include btm-brdr;
padding: 20px 0;
}
h4.catalog-title {
font-weight: normal;
font-size: 1.5em;
color: $blue;
top: 0;
padding: 0;
margin: 0;
text-align: center;
}
h6 {
font-weight: normal;
font-size: 1em;
color: $pale-grey;
padding: 0 10%;
margin: 0;
text-align: center;
}
img.cat-img {
#include center;
}
img.rocket {
width: 40%;
margin-top: 30px;
}
img.wizard {
width: 50%;
margin-top: 10%;
margin-bottom: 10%;
}
img.order {
width: 60%;
margin-top: 10%;
margin-bottom: 10%;
}
#media min-width 568px I actually wanted the image to be a smaller percentage scale and here's my Sass that i added to this media query:
img.rocket {
width: 30%;
margin-top: 30px;
}
img.wizard {
width: 40%;
margin-top: 10%;
margin-bottom: 10%;
}
img.order {
width: 50%;
margin-top: 10%;
margin-bottom: 10%;
}
My thinking behind this is that since i'm only adding styles that are changing as the viewport gets larger i don't have to add all of the Sass for this block (as i did at the 320px media query) but rather just add the rules that I want changed.
However what is happening is that the 320px media query image percentage size is overriding my 568px media query percentage image size when the viewport is at 568px and i'm not sure why.
Attached is a screenshot of what is going on in DevTools and i suspect that the reason that the 320px style is overriding the 568px style is due to more specificity since it notes all the parent elements of this particular image.
However i've attempted to remove the specificity from the 320px file so that the only rules that i want to be affected on the 320px file would be. In other words not include the entire block and its children but only the classes i want adjusted at this specific viewport size and that didn't work either.
Does this make sense?
Here is the screenshot:
In the 568px query, the image is targeted as:
img.rocket { ... }
In the 320px query, it's:
section.catalog-grid img.rocket { ... }
Since you have the additional specificity on the 320px rule, it will always override the less-specific rule no matter where it is located in the style sheet. You'll either need to match that specificity in your 568px rule, or reduce the specificity of the 320px rule.
In your sass, it looks like you have image.rocket contained inside the section.catalog-grid block:
section.catalog-grid {
...
img.rocket { ... }
}
That creates the compiled rule you're seeing.

Resources