Given the following HTML structure:
<div id="a">
A
<div id="b">
B
</div>
</div>
...and the following Singularity SCSS:
$grids: 6;
$gutters: .1;
$gutter-styles: 'split';
div#a {
#include grid-span(5,2)
}
div#b {
// #todo: position and width.
}
...I want to create a layout like this, where B is pulled left, out of its container A, by 1 column, and spans the 2 leftmost columns:
-----------
| A |
----- |
| B | |
----- |
| |
-----------
Of course I can do the math myself, but I feel like this should be possible using Singularity mixins and functions (after all, that's why I'm using a grid framework :-)) However, I can't get the dimensions and positioning of B correct.
Which Singularity mixins and/or functions do I use to set the width (column span) and position (negative margin-left) of div#b?
The answer highly depends on what flow you want inside the #A block.
Keeping the flow
The simpliest thing to do is to pull the #B block outside with a negative margin.
To do that, you should not use the grid-span() mixin. Instead, use the width and margin CSS properties. Values for those properties can be calculated with the column-span() and gutter-span() helper functions.
Those helper functions accept the $grid argument which stands for grid context. You should provide the grid context of the #A block, which is one column less than the main grid.
$grids: 6
$gutters: .1
$gutter-styles: 'split'
$a-columns-width: 5
#a
+grid-span($a-columns-width,2)
overflow: visible
#b
width: column-span(2, 1, $grid: $a-columns-width)
margin-left: - column-span(1, 1, $grid: $a-columns-width) - gutter-span($grid: $a-columns-width)
Please have a look at the demo: http://sassbin.com/gist/6676220/
Removing #B out of the flow
But the #B block is not taken out of the flow. It still occupies the whole width of the #A block, so you can't put anything to the right of #B.
If you need to put some text and stuff to the right of #B, you should consider using another approach. Absolute positioning is what comes to my mind.
The solution will be more complicated. If you want me to come up with one, please explain your task in more detail. Provide a graphical template, maybe.
You will also have to use some trick to prevent #A's content from being covered by #B.
Flat HTML structure makes things simple
Also, why do you need the nested structure (#B inside #A) in the first place? If you make the structure flat, it becomes plain simple to position the blocks:
#a
+grid-span(5,2)
#b
+grid-span(2,1)
margin-top: 4em
Demo: http://sassbin.com/gist/6676193/
#A's content appearing under #B is still an issue though.
PS If you're not satisfied with the answer, please explain the task in more detail and provide a graphical illustration of the desired page with all #A's contents.
Something like this seems like what you are looking for: http://sassmeister.com/gist/6663743
Related
I need to implement a plotly.js chart on a page with a very restricted width. As a result, a tooltip is partially cut. Is it possible to cause tooltip not to be limited by plotly.js container size?
My code example at codepen: https://codepen.io/anatoly314/pen/gOavXzZ?editors=1111
//my single trace defined as following but it's better to see example at codepen
const yValue1 = [1000];
const trace1 = {
x: [1],
y: yValue1,
name: `Model 1`,
text: yValue1.map(value => Math.abs(value)),
type: 'bar',
textposition: 'outside'
};
It is, by design, not possible for any part of the chart to overflow its container.
I would say it is wrong to say that by design this is not possible! It is a bit hacky, but when you add the following lines, it shows the label outside of svg:
svg.main-svg,svg.main-svg *
{
overflow:visible !important;
}
The answer given by rokdd works. However the css selector should be more specific, otherwise it's natural that you will introduce subtle bugs (particularly if you need to scroll the content where the plotly chart is contained).
If we look at the DOM tree constructed by Plotly, we find that the tooltips are created inside the <g class="hoverlayer"></g> element (which is a direct child of one of the three <svg class="main-svg"></svg>). So that parent (that svg.main-svg element) is only one that needs to affected.
The ideal css selector in this case would be the :has selector. However it's still not supported (as of 2022): https://css-tricks.com/the-css-has-selector/
So the next simplest thing is to use a little bit of javascript right after we call Plotly.newPlot:
// get the correct svg element
var mainSvgEl = document.querySelector('#positive g.hoverlayer').parentElement;
mainSvgEl.style['overflow'] = 'visible';
Or in a more generic way (works for any chart):
Array.from(document.querySelectorAll('g.hoverlayer')).forEach(hoverEl => {
let mainSvgEl = hoverEl.parentElement;
mainSvgEl.style['overflow'] = 'visible';
});
Please look at this gist:
http://sassmeister.com/gist/6d575ec85663865fa567
There you can see a placehold.it thumbnail grid realized via float-span
What i need now is:
The padding-left of the first .item in each row should be 0
The padding-right of the last .item in each row should be 0
this would then end up in the thumbnail grid perfectly aligning with the rest of the content (e.g. the lorem ipsum text)
What is the beast way to achieve this with singularitygs?
UPD 2014-07-21
what i need can be seen in this screen:
i don't need another padding style, i need the padding from the first and last item in each row removed. this can't be done via css, because the sass calculations would be wrong.
UPD 2014-07-30
based on various sources, i managed to establish this mixin:
#mixin thegrid($layout, $cols, $el: "div", $thegutter: .1){
#include layout($layout, $gutter: $thegutter) {
#for $i from 1 through $cols {
#if $i == 1 {
#{$el}:nth-child(#{$cols}n+#{$i}) {
#include isolation-span(1, $i, left);
}
}
#else if $i < $cols {
#{$el}:nth-child(#{$cols}n+#{$i}) {
#include isolation-span(1, $i, none);
}
}
#else {
#{$el}:nth-child(#{$cols}n+#{$i}) {
#include isolation-span(1, $i, right);
}
}
}
}
}
which can be called e.g. via:
$layout: 1 1 1;
#include thegrid($layout, 3, $el: ".item");
an example can be seen here: http://sassmeister.com/gist/7a45960747ad3d4bbf56
Not sure what you mean.
You're applying gutters with an absolute value. This is what Singularity calls fixed gutters.
Singularity realizes fixed gutters by applying padding to grid elements.
Padding can be applied in two styles:
split: the gutter size is divided by two and the resulting value is applied as left and right padding to every grid item.
opposite: the value of gutter size is applied as right padding to every item except items occupying the last column.
So if you are unhappy with split gutters, switch to opposite gutters. That's the default behavior, so you can simply comment out #include add-gutter-style('split');.
If you are unhappy with either gutter style, well, you can manually remove padding that you don't need. This doesn't make a lot of sense because if you apply zero padding to items other than occupying the first and the last columns, you will distort your grid. And if you apply them only to the items occupying the first and the last columns, you basically get the same setup as with opposite gutter styles.
You might get better help if you make a pencil drawing of desired layout.
UPD 2014-07-21
OK, now it's clear what you mean.
So you basically want split gutters for the outer level and opposite gutters for the inner level. You're already using the layout() mixin required to override grid settings, so you could just tell it to override gutter styles, e. g.:
#mixin layout(2, $gutter-style: 'opposite') {
Unfortunately, due to the fact that Singularity creates fixed gutters via padding, they only play nice in split mode. In opposite mode fixed gutters produce uneven columns.
So you'll have to use relative gutters:
#mixin layout(2, 0.1, $gutter-style: 'opposite') {
There are a couple of things you have to keep in mind:
Spanning the last item in each row separately.
With the opposite gutter style, the last item in each row is special: it contains no right gutter. So you will have to tell Singularity which item is the last one in row.
To do this, we will use the :nth-child(Xn + Y) selector, where X is the number of items in the row and Y is the number of target item in the row. As we're targeting the last item, X and Y will be equal:
#include float-span(1);
&:nth-child(4n + 4) {
#include float-span(1, last);
}
Isolating media queries.
Once you do that for each breakpoint, you'll end up with styles applied to different items in different breakpoints. Those styles will not be overridden and thus will leak from smaller to larger breakpoints, breaking the layout.
You could override them manually, but that's a lot of thankless job. Instead, isolate your media queries so that styles don't leak:
$beforeMediumBreakpoint: max-width 799px;
$mediumBreakpoint: 800px;
// Mobile view (formerly without a media query)
#include breakpoint($beforeMediumBreakpoint) {
Demo: http://sassmeister.com/gist/dd9f1af025900d7e63db
PS A piece of advice from me: don't use fixed gutters and split mode. Use fluid gutters and the default opposite mode. This will save you from a lot of trouble! You can always simulate split gutters by applying padding to the outermost container.
You can do some math to calculate relative padding for the container that will be equal to the gutter between grid items! With the magic of math, you can even apply bottom margins to grid items equal to grid gutters, producing a beautiful uniform thumbnail grid.
I've created a nifty extension Singularity Quick Spanner that can reduce the amount of work you need to do to set up thumbnail grids. See it in action (note vertical gutters equal to horizontal gutters).
How do I get nested grid with Singularity?
I've made a simple grid and need nested grids with floating method.
My sample: http://sassmeister.com/gist/7326030
You should understand two things:
Singularity applies relative widths to columns.
All it does is generating CSS, completely unaware of your HTML structure.
So, if you apply a float span to a class, it will get width: 33%, for example. Every element with that class will have width: 33%, regardless of its nesting. This means that you can't create nested grids with a single level of non-semantic classes. You'll need two or more levels:
span1, span2, span3...
grid1-span1, grid1-span2, grid1-span3 ... grid2-span1, grid2-span2, grid2-span3...
This results in bloated CSS. That's why the non-semantic approach should never be used when your environment allows you use the semantic approach (and Sass does lets you do that with little effort):
Structure:
#page
#foo.container
.subcontainer
.column Foo
.subcontainer
.column Bar
#bar.container
.column Baz
.column Quux
Styles:
$grids: 12
$gutters: 0.2
#foo
.subcontainer
+float-span(6)
&:nth-child(2n)
+float-span(6, last)
.column
+layout(6)
+float-span(3)
&:nth-child(2n)
+float-span(3, last)
#bar
.column
+float-span(6)
&:nth-child(2n)
+float-span(6, last)
Demo: http://sassmeister.com/gist/7360259
Also note two things:
You don't need to span the first-level container, it's already 100% wide.
You should be very careful with fixed margins in nested grids.
I have a grid set up of thumbnail images, currently 4 thumbs per row. To make sure they line up i have this snippet of code:
li:nth-child(5) { margin-left: 0;}
What I have tried to do is this but I am getting a syntax error:
$galleryGrid: 5;
li:nth-child($galleryGrid) { margin-left: 0;}
If I wanted to alter the nth-child to use another value, such as 10 (so I can have 8 thumbs in a row), I assumed this would work.
Is this not possible or am I just doing incorrectly?!
Thanks in advance for you help.
You need to use variable interpolation to allow nth-child to be a variable.
$galleryGrid: 5;
li:nth-child(#{$galleryGrid}) { margin-left: 0;}
Generates
li:nth-child(5){margin-left:0}
This markup is fine if you have absolute control over the images and layout to ensure that your elements always wrap in such a way that every 5th one begins a new row. If you cannot make such guarantees, setting negative margins on the parent element is a better way to go.
I'm trying to check in Selenium if an element has a green border or not.
i can use //div[#id="target"]/#style to get the parsed style string applied... and use string search to search for the border... i have to work around some brosers showing the shorthand (border: solid 3px green) and other showing the expanded (border-style: solid; border-color: green....) ...but how could i do that more cleanly?
ideally something like: //div[#id="target"]/#style.borderColor
I also would like to avoid using the contains selector because the syntax is awful. But if it's the only way, so be it. of course.
XPath doesn't know anything about CSS styles, it doesn't understand the attributes and takes them just as simple strings. It would be weird if a XML query language understood CSS styles, right?
Besides, the getAttribute() uses a construct similar to XPath, but not XPath! It also selects the attribute via # sign, right. But consider this locator: "id=target#style". It would work, but it's definitely no XPath.
It would also return the explicitly set style attribute, not it's internal computed value, so it's useless unless there actually is a style attribute on the element. If there is style attribute defined, go for it.
Selenium itself can't give you the right answer (WebDriver has getCssValue(), but there's no counterpart for it in Selenium RC, afaik).
Therefore, the only way to get the computed style (the final value computed from all sources) of an element in Selenium RC is via JavaScript.
The script that has been working for me for ages (after a slight edit) is this (from quirksmode.org):
function getStyle(id, stylePropJs, stylePropCss) {
var x = document.getElementById(id);
if (x.currentStyle)
var y = x.currentStyle[stylePropJs];
else if (window.getComputedStyle)
var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(stylePropCss);
return y;
}
Note that IE needs a JavaScript name of the property, but every other browser uses CSS names. Also, you can't use the shorthand property and you definitely must use the expanded one. Therefore, in your case:
String script = "var x = document.getElementById('target');" +
"if (x.currentStyle) var y = x.currentStyle['borderTopColor'];" +
"else if (window.getComputedStyle) var y = document.defaultView.getComputedStyle(x,null).getPropertyValue('border-top-color');" +
"y;";
String color = selenium.getEval(script);
This returns the color of the top border (yep, you'll need to call it four times in order to get the whole border) of the target element. But guess what! Every browser returns the color in a different format. Fortunately, at least in Java, there's a Color class that can easily reformat it:
String color = Color.fromString(color).asHex();
Now that you have a hex encoded color stored, you can trivially make check whether it's green or not.