Susy Next content source ordered layout - css

I'm having a few issues understanding how to produce the following layout using Susy Next.
While this is pretty strait forward with strait CSS I can't seem to get my head around doing this cleanly in Susy, or at all really.
A caveat here is that I can't add any extra wrappers into the layout, it's just four DIV blocks and has to be that way. The other caveat is that I would really prefer to be using Susy Next (I am using alpha4 at the moment).
Really kind of hoping I am just not seeing the woods for the tress as I have only been using Susy for a few weeks.
The source order is:
first
second
third
fourth
The required layout is:
-----------------------------------------
| fourth | first |
| ----------------------------
| | second | third |
-----------------------------------------
Update 1.
Update to add my current CSS solution, I've included the markup and all the CSS taking affect on the page, for completeness:
<main>
<div class="container">
<div class="region region-first"></div>
<div class="region region-second"></div>
<div class="region region-third"></div>
<div class="region region-fourth"></div>
</div>
</main>
.container {
*zoom: 1;
max-width: 73.75em;
margin-left: auto;
margin-right: auto;
padding: 0 1.25em;
}
.container:after {
content: "";
display: table;
clear: both;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
main .region:first-child {
width: 66.1016949%;
float: right;
}
main .region:nth-child(2) {
clear: right;
float: right;
margin-right: 33.8983051%;
width: 32.2033898%;
}
main .region:nth-child(3) {
margin-right: -66.1016949%;
width: 32.2033898%;
float: right;
}
main .region:last-child {
width: 32.2033898%;
margin: 0;
}
Some Ideas for a Solution?
I started to poke the internals of Susy Next and tried called the span() function directly to just get widths, hooray this works where I just need a value for width: , however...
...where I am doing margin-right: span(4 + $gutter) the margin-right value needs to be the same value as push or pre would return, but I can't quite understand all the internals of how they work, my "magical float" of .75 when calculating $gutter is ever so slightly inaccurate, it might be right, but of course change a value in set-grid and it can be wrong, so its a rough guess at best.
What I need is a way to get the same value as pre would return, but of course just the value OR just a whole better way of doing the whole thing :)
.region {
&:first-child {
#include span(8 omega of 12);
}
&:nth-child(2) {
$gutter: $gutters * .75;
margin-right: span(4 + $gutter);
width: span(4);
float: right;
clear: right;
}
&:nth-child(3) {
margin-right: - span(8);
width: span(4);
float: right;
}
&:last-child {
width: span(4);
}
}

You're right - it's totally possible and not even very hard in Susy Next:
.region {
&:first-child { #include span(last 8); }
&:nth-child(2) {
clear: right;
#include span(4 at 5 isolate);
}
&:nth-child(3) { #include span(last 4 isolate); }
&:last-child { width: span(4); }
}
The isolation option allows you to position elements at specific locations on the grid.

I will answer my own question. You will need to read through the original question as to why this is an answer - essentially what it comes down to is the right tool for the job. I was trying to solve my problem using Susy mixins (initially), however turning to Susy functions helped get me most of the way to a solution.
The final part is to write my own function to return the right value that I needed for the nth-child(2) div, it needs a margin-right to push it back into position the correct amount. Copying the internals of the Susy pre mixin was the obvious course of action here, and it worked, hooray!
#function elf-margin-value(
$span,
$columns
) {
$this: $span, $columns;
$value: if(index($this, outer), $this, append($this, outer));
#return span($value);
}
So in my code I can use it like this:
margin-right: elf-margin-value(4, 12);
Minor issue - I know what index and append are doing, but not I'm not quite sure about outer.
Not the place to discuss but I wonder if this abstraction would be good for Susy Next, rather than baking this same/similar logic into several mixins. I would benefit at least :)
Anyway this is how I solved this for now, I am still very interested to hear if Eric has some advice for this and if my solution can be done easier/better.
The solution thus far is the following:
$to: to($flow);
.region {
&:first-child {
#include span(8 omega of 12);
}
&:nth-child(2) {
margin-#{$to}: elf-margin-value(4, 12);
width: span(4);
float: $to;
clear: $to;
}
&:nth-child(3) {
margin-#{$to}: - span(8);
width: span(4);
float: $to;
}
&:last-child {
width: span(4);
}
}

Related

Approach to reduce SASS generated lines

In my curently workflow, I use some mixins to easier responsive breakpoints code. I also use gulp to process and compress those generated CSS. Example below:
#footer {
.block-contacts {
.social_title {
display: block;
#include desktop() {
display: inline-block
}
&:before {
width: 100vw;
#include desktop() {
width: 50vw;
}
}
}
}
}
After the process of compile and minify, this code above ends up repeating the #media rule, like this:
#footer .block-contacts .social_title {
display: block;
}
#media(min-width: 64rem){
#footer .block-contacts .social_title {
display:inline-block
}
}
#footer .block-contacts:before {
width:100vw;
}
#media(min-width: 64rem){
#footer .block-contacts:before {
width:50vw
}
}
In this example I used only a "small" hierarchy and selector, but this in the whole project I guess it could be a negative impact for performance or assets size.
I know I can avoid this duplicity recreating the rule structure inner a single #include desktop() at the end of file.
My question is if there is another way, authomated, to reduce those lines creation, something I can do in the mixin that join all of this calls, or some gulp process/plugin, or even in the SASS...

scss continue name with interpolation and `#at-root`

I am trying to fully understand the ampersand (&) and interpolation operators in sass, while also following bem. For example, I have a table block declared like so:
.table {
width: 60%;
&__title {
// omit code
}
&__data {
display: grid;
width: 100%;
& > #{#at-root}__key + #{#at-root}__value > * { // <- ISSUE HERE
// give all direct, non text child nodes margin below
margin-bottom: 0.5em;
}
}
}
and used like:
<div class='table'>
<div class='table__title'>...</div>
<div class='table__data'>
<div class='table__key'>...</div>
<div class='table__value'>...</div>
</div>
</div>
See line 9 of the sass; here the expected compiled result would be
.table__data > .table__key + .table__value > * {
margin-bottom: 0.5em;
}
but of course #at-root is not a variable so an error is thrown
SassError: Invalid CSS after "#": expected expression (e.g. 1px, bold), was "#at-root}__key + #{"
Does anything like my attempt exist, can/should I somehow combine the #at-root element with classes I'm using?
Articles I've already tried:
Append the parent selector to the end with Sass
EDIT made the question clearer
What I do when I actually deem this necessary is to just create your reference from the root. It's kind of like the old days when you often had to declare that = this scenarios (well not really but you get the idea lol).
However, generally I avoid this kind of deep nesting unless it's genuinely required to avoid too many levels of specificity (habit from the old days when such noticeably things effected performance.
See example below, and a codepen to tinker
.table {
$root: &; // <-- create reference to root that allows interpolation.
width: 60%;
&__title {
// omit code
}
&__data {
display: grid;
width: 100%;
& > #{$root}__key + #{$root}__value > * { // <- ISSUE HERE
// give all direct, non text child nodes margin below
margin-bottom: 0.5em;
}
}
}
...and the compiled output...
.table {
width: 60%;
}
.table__data {
display: grid;
width: 100%;
}
.table__data > .table__key + .table__value > * {
margin-bottom: 0.5em;
}

"Resting" & in Sass

I'm importing sass classes from another project and want to provide a wrapper to keep these styles localised.
My wrapper looks like this
.my-wrapper {
#include "framework-main"
}
I first looked fine but then I noticed that some tiles are missing. The problem is that the framework sass files use heavily reference to parent: &. This works fine for them but when I apply the wrapper it's get injected everywhere.
How can I make the wrapper a prefix only?
To illustrate:
SASS:
.wrapper {
// reset here somehow, I have no control over the nested code.
.parent {
&--child1 &--child2 {
width: 10%;
}
}
}
What I want:
.wrapper .parent--child1 .parent--child2 {
width: 10%;
}
What I get:
.wrapper .parent--child1 .wrapper .parent--child2 {
width: 10%;
}
Is this even possible?
Yes, it is possible, there is just small mistake in your code - you don't need . in front of &--child so it will not break selector construction:
.wrapper {
// reset here somehow
.parent {
&--child {
&--grand-child{
width: 10%;
}
}
}
}
gives
.wrapper .parent--child--grand-child {
width: 10%;
}

Creating a fluid grid - percentages seem to mess up

I was looking at the Skeleton framework (getskeleton.com), but I wanted a fluid grid system. I'm also interested in the inner workings of these grids, so I decided to roll my own.
However, I'm running into trouble with the two.columns percentages. All other column widths work fine. First of, here's what's happening:
There's clearly something wrong with the second row, and I really can't figure out what it is.
My code for this layout is as follows:
$max-width: 600px;
.container {
#include container($max-width);
.column, .columns {
#include columns($max-width);
}
.one.column, .one.columns { width: perc(30px, $max-width); }
.two.columns { width: perc(80px, $max-width); }
.three.columns { width: perc(130px, $max-width); }
.four.columns { width: perc(180px, $max-width); }
.five.columns { width: perc(230px, $max-width); }
.six.columns { width: perc(280px, $max-width); }
.seven.columns { width: perc(330px, $max-width); }
.eight.columns { width: perc(380px, $max-width); }
.nine.columns { width: perc(430px, $max-width); }
.ten.columns { width: perc(480px, $max-width); }
.eleven.columns { width: perc(530px, $max-width); }
.twelve.columns { width: perc(580px, $max-width); }
Here are the mixins/functions that I used, not sure if that's important:
#function perc($width, $container-width) {
#return percentage($width / $container-width);
}
#mixin container($width) {
position: relative;
width: $width;
margin: 0 auto;
padding: 0;
}
#mixin columns($max-width) {
float: left;
display: inline;
margin: 0 10px;
}
The code in the HTML file is just:
<% 6.times do %>
<div class="two columns box"></div>
<% end %>
I figured if there was something wrong with the calculation of the percentages, all rows would mess up in one way or another. However, it's just the second one.. If anyone sees what's going on here, please enlighten me?
I put the processed CSS on pastebin: http://pastebin.com/bxq1a5Ge
Thanks in advance.
I think you need to convert your margins into percentages as well. Everytime a div spans more than 1 column the gutter width of 20px is converted into a percentage as part of the block width. This will end up going wrong at some point.
Another option is that it is a rounding issue as the browser can't quite convert the percentage values into pixel values neatly.
I've set up a basic jsfiddle of the issue since jsfiddle supports SCSS. The example shows option 2 as a good candidate but I'd advise changing all widths to percentages.
Apparently
perc(80px, 600px) gives 13.333%.
The issue got fixed when I used width: 13.3333333%.

Less - How to insert an #variable into property (as opposed to the value)

In less.js, I'm able to replace values with variables with no problems.
#gutter: 20px;
margin-left:e(%("-%d"), #gutter);
When trying to replace properties with variables, I get errors. How would I perform the following in Less?
#gutter: 20px;
#direction: left;
e(%("margin-%d"), #direction):e(%("-%d"), #gutter);
Thanks to Alvivi for the solution and research (you get the reward for that). I decided to add the following as the actual answer since this is a real way to set it up instead of looking at .blah() pseudo code..
Here's a real strategy for setting it up:
#gutter: 20px;
#dir: left;
#dirOp: right;
then create mixins to enhance margin and padding like so:
.margin(left, #dist:#gutter) {
margin-left:#dist;
}
.margin(right, #dist:#gutter) {
margin-right:#dist;
}
.padding(left, #dist:#gutter) {
padding-left:#dist;
}
.padding(right, #dist:#gutter) {
padding-right:#dist;
}
.lr(left, #dist: 0) {
left: #dist;
}
.lr(right, #dist: 0) {
right: #dist;
}
.. then you can just
#selector {
.margin(#dir);
}
or
#selector {
.margin(#dirOp, 10px);
}
all together:
#selector {
.margin(#dir);
.margin(#dirOp, 50px);
.padding(#dir, 10px);
.padding(#dirOp);
float:#dir;
text-align:#dirOp;
position:absolute;
.lr(#dir);
}
Easy breezy LTR/RTL with LESS! Woot!
Escaping, as says the documentation, is used to create CSS values (not properties).
There is a discussion with some workarounds here. One would be using parametric mixins. For example:
.g () { /* Common properties */ }
.g (right) { margin-right: e(...) }
.g (left) { margin-left: e(...) }

Resources