Making this LESS Mixin more efficient and less redundant? - less

so for a website project I had to create a LESS Mixin which I had never done before. I have the feeling that it is not as efficient as it could be and may be a little redundant. I looked through it but couldnt think of a better way to do it. Maybe you can give me some advice? Dont get me wrong, its working perfectly fine but as mentioned I guess I could do it a little easier when it comes to the LESS code.
So here it is:
http://jsfiddle.net/T2Xe9/747/
Example HTML:
<style media="screen">
div {
background: crimson;
width: 200px;
height: 100px;
position: relative;
float: left;
margin-right: 20px;
}
</style>
<div class="example-1"></div>
<div class="example-2"></div>
<div class="example-3"></div>
<div class="example-4"></div>
Mixin with examples:
.clipping(#colorOne; #colorTwo; #width; #direction; #position; #side) {
display: inline-block;
width: #width;
height: 20%;
position: absolute;
content: " ";
& when (#direction = 'up') {
background: linear-gradient(to top left, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
}
& when (#direction = 'down') {
background: linear-gradient(to top right, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
}
& when (#position = top) {
top: 0;
}
& when (#position = bottom) {
bottom: 0;
}
& when (#side = 'left') {
left: 0;
}
& when (#side = 'right') {
right: 0;
}
}
.clipping-single(#colorOne; #colorTwo; #direction; #position) {
&:before {
.clipping(#colorOne; #colorTwo; 100%; #direction; #position; 'left');
}
}
.clipping-double(#colorOne; #colorTwo; #direction; #position) {
& when (#direction = 'up') {
&:before {
.clipping(#colorOne; #colorTwo; 50%; 'up'; #position; 'left');
}
&:after {
.clipping(#colorOne; #colorTwo; 50%; 'down'; #position; 'right');
}
}
& when (#direction = 'down') {
&:before {
.clipping(#colorOne; #colorTwo; 50%; 'down'; #position; 'left');
}
&:after {
.clipping(#colorOne; #colorTwo; 50%; 'up'; #position; 'right');
}
}
}
.example-1 {
.clipping-double(crimson, #fff, 'up', top);
}
.example-2 {
.clipping-double(#fff, crimson, 'down', bottom);
}
.example-3 {
.clipping-single(#fff, crimson, 'down', bottom);
}
.example-4 {
.clipping-single(crimson, #fff, 'up', top);
}

I have two suggestions for you. Both will reduce the redundancy and produce the same CSS as the original version. If more efficient means less lines of SASS code then this is also the case.
& when (#position = top) {
top: 0;
}
& when (#position = bottom) {
bottom: 0;
}
can be replace with
#{position}: 0;
and the same for #{side}: 0; but you would have to pass left instead of 'left' as an argument.
The second suggestion is to refactor the line where you set the linear-gradient. The only variable is the direction so I would make this a SASS variable to avoid the redundancy of the other linear-gradient parameters.
& when (#direction = 'up') {
background: linear-gradient(to top left, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
}
& when (#direction = 'down') {
background: linear-gradient(to top right, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
}
becomes
.define-gradient-direction(#direction);
.define-gradient-direction('up') { #gradientDir: to top left; }
.define-gradient-direction('down') { #gradientDir: to top right; }
background: linear-gradient(#gradientDir, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
Full code
.clipping(#colorOne; #colorTwo; #width; #direction; #position; #side) {
.define-gradient-direction(#direction);
.define-gradient-direction('up') { #gradientDir: to top left; }
.define-gradient-direction('down') { #gradientDir: to top right; }
display: inline-block;
width: #width;
height: 20%;
position: absolute;
content: " ";
background: linear-gradient(#gradientDir, #colorOne 0%, #colorOne 50%, #colorTwo 50%, #colorTwo 100%);
#{position}: 0;
#{side}: 0;
}
.clipping-single(#colorOne; #colorTwo; #direction; #position) {
&:before {
.clipping(#colorOne; #colorTwo; 100%; #direction; #position; left);
}
}
.clipping-double(#colorOne; #colorTwo; #direction; #position) {
& when (#direction = 'up') {
&:before {
.clipping(#colorOne; #colorTwo; 50%; 'up'; #position; left);
}
&:after {
.clipping(#colorOne; #colorTwo; 50%; 'down'; #position; right);
}
}
& when (#direction = 'down') {
&:before {
.clipping(#colorOne; #colorTwo; 50%; 'down'; #position; left);
}
&:after {
.clipping(#colorOne; #colorTwo; 50%; 'up'; #position; right);
}
}
}
.example-1 {
.clipping-double(crimson, #fff, 'up', top);
}
.example-2 {
.clipping-double(#fff, crimson, 'down', bottom);
}
.example-3 {
.clipping-single(#fff, crimson, 'down', bottom);
}
.example-4 {
.clipping-single(crimson, #fff, 'up', top);
}
Edit: thanks to seven-phases-max for pointing out an improvement in the comments. It's now part of the snippet.

Related

What does "$root: &" mean in sass?

I'm trying to understand sass files of Splide ( https://splidejs.com/ ).
In many files there are codes like this one
.splide {
$root: &;
&--ttb {
> #{$root}__pagination {
display: flex;
right: 1em;
bottom: 50%;
left: auto;
flex-direction: column;
transform: translate(0, 50%);
#{$root}__pagination__page {
width: $indicator-height;
height: $indicator-width;
}
}
}
}
What the $root: &; means?
In your snippet, $root is just the name of the variable.
You could give it another name, like $foo.
$root: & is equivalent here to $root: .splide as & in sass refers to the parent selector.
It means that:
.splide {
$root: &;
&--ttb {
> #{$root}__pagination {
display: flex;
right: 1em;
bottom: 50%;
left: auto;
flex-direction: column;
transform: translate(0, 50%);
#{$root}__pagination__page {
width: $indicator-height;
height: $indicator-width;
}
}
}
}
Is equivalent to:
.splide {
&--ttb {
> .splide__pagination {
display: flex;
right: 1em;
bottom: 50%;
left: auto;
flex-direction: column;
transform: translate(0, 50%);
.splide__pagination__page {
width: $indicator-height;
height: $indicator-width;
}
}
}
}
And will compile to:
.splide--ttb > .splide__pagination {}
.splide--ttb > .splide__pagination .splide__pagination__page {}

How to integrate jsplumb in vuejs?

I have tried jsplumb script in .html file under the script tag. This is working fine.
<body>
<div id="q-app"></div>
<!-- built files will be auto injected -->
<script>
jsPlumb.ready(function() {
jsPlumb.connect({
source:"item_left",
target:"item_right",
endpoint:"Rectangle"
});
jsPlumb.draggable("item_left");
jsPlumb.draggable("item_right");
});
</script>
</body>
But now i want to integrate this jsplumb code/script in .vue file.I tried to put this script in .vue file under script tag, but i did not get any output except an blank page with zero errors. How can i proceed further?.Guide me with some simple example.
You can try this:
mydraggableview.vue
<template>
<div id="diagramContainer">
<div id="item_left" class="item"></div>
<div id="item_right" class="item" style="margin-left:50px;"></div>
</div>
</template>
<script>
import jsplumb from 'jsplumb'
export default {
props: ['yourProps'],
data() {
return {
your: data
}
},
mounted(){
jsPlumb.ready(function() {
jsPlumb.connect({
source:"item_left",
target:"item_right",
endpoint:"Rectangle"
})
})
}
}
</script>
Then you can import where you are going to use it.
otherfile.js
<script>
import myDraggableComponent from './path/to/component/mydraggableview'
</script>
and use it as directive or inside your component.
I managed to put together working code based on jsplumb demo community example -
<template>
<div id="canvas" class="jtk-demo-canvas canvas-wide flowchart-demo jtk-surface jtk-surface-nopan">
<div id="flowchartWindow1" class="window jtk-node">1</div>
<div id="flowchartWindow2" class="window jtk-node">2</div>
<div id="flowchartWindow3" class="window jtk-node">3</div>
<div id="flowchartWindow4" class="window jtk-node">4</div>
</div>
</template>
<script>
import { jsPlumb as JSPlumb } from 'jsplumb'
export default {
name: 'JsPlumb',
data () {
return {
}
},
mounted () {
JSPlumb.ready(function() {
var instance = window.jsp = JSPlumb.getInstance({
// default drag options
DragOptions: { cursor: 'pointer', zIndex: 2000 },
// the overlays to decorate each connection with. note that the label overlay uses a function to generate the label text; in this
// case it returns the 'labelText' member that we set on each connection in the 'init' method below.
ConnectionOverlays: [
[ "Arrow", {
location: 1,
visible:true,
width:11,
length:11,
id:"ARROW",
events:{
click:function() { alert("you clicked on the arrow overlay")}
}
} ],
[ "Label", {
location: 0.1,
id: "label",
cssClass: "aLabel",
events:{
tap:function() { alert("hey"); }
}
}]
],
Container: "canvas"
});
var basicType = {
connector: "StateMachine",
paintStyle: { stroke: "red", strokeWidth: 4 },
hoverPaintStyle: { stroke: "blue" },
overlays: [
"Arrow"
]
};
instance.registerConnectionType("basic", basicType);
// this is the paint style for the connecting lines..
var connectorPaintStyle = {
strokeWidth: 2,
stroke: "#61B7CF",
joinstyle: "round",
outlineStroke: "white",
outlineWidth: 2
},
// .. and this is the hover style.
connectorHoverStyle = {
strokeWidth: 3,
stroke: "#216477",
outlineWidth: 5,
outlineStroke: "white"
},
endpointHoverStyle = {
fill: "#216477",
stroke: "#216477"
},
// the definition of source endpoints (the small blue ones)
sourceEndpoint = {
endpoint: "Dot",
paintStyle: {
stroke: "#7AB02C",
fill: "transparent",
radius: 7,
strokeWidth: 1
},
isSource: true,
connector: [ "Flowchart", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true } ],
connectorStyle: connectorPaintStyle,
hoverPaintStyle: endpointHoverStyle,
connectorHoverStyle: connectorHoverStyle,
dragOptions: {},
overlays: [
[ "Label", {
location: [0.5, 1.5],
label: "Drag",
cssClass: "endpointSourceLabel",
visible:false
} ]
]
},
// the definition of target endpoints (will appear when the user drags a connection)
targetEndpoint = {
endpoint: "Dot",
paintStyle: { fill: "#7AB02C", radius: 7 },
hoverPaintStyle: endpointHoverStyle,
maxConnections: -1,
dropOptions: { hoverClass: "hover", activeClass: "active" },
isTarget: true,
overlays: [
[ "Label", { location: [0.5, -0.5], label: "Drop", cssClass: "endpointTargetLabel", visible:false } ]
]
},
init = function (connection) {
connection.getOverlay("label").setLabel(connection.sourceId.substring(15) + "-" + connection.targetId.substring(15));
};
var _addEndpoints = function (toId, sourceAnchors, targetAnchors) {
for (var i = 0; i < sourceAnchors.length; i++) {
var sourceUUID = toId + sourceAnchors[i];
instance.addEndpoint("flowchart" + toId, sourceEndpoint, {
anchor: sourceAnchors[i], uuid: sourceUUID
});
}
for (var j = 0; j < targetAnchors.length; j++) {
var targetUUID = toId + targetAnchors[j];
instance.addEndpoint("flowchart" + toId, targetEndpoint, { anchor: targetAnchors[j], uuid: targetUUID });
}
};
// suspend drawing and initialise.
instance.batch(function () {
_addEndpoints("Window4", ["TopCenter", "BottomCenter"], ["LeftMiddle", "RightMiddle"]);
_addEndpoints("Window2", ["LeftMiddle", "BottomCenter"], ["TopCenter", "RightMiddle"]);
_addEndpoints("Window3", ["RightMiddle", "BottomCenter"], ["LeftMiddle", "TopCenter"]);
_addEndpoints("Window1", ["LeftMiddle", "RightMiddle"], ["TopCenter", "BottomCenter"]);
// listen for new connections; initialise them the same way we initialise the connections at startup.
instance.bind("connection", function (connInfo, originalEvent) {
init(connInfo.connection);
});
// make all the window divs draggable
instance.draggable(JSPlumb.getSelector(".flowchart-demo .window"), { grid: [20, 20] });
// THIS DEMO ONLY USES getSelector FOR CONVENIENCE. Use your library's appropriate selector
// method, or document.querySelectorAll:
//JSPlumb.draggable(document.querySelectorAll(".window"), { grid: [20, 20] });
// connect a few up
instance.connect({uuids: ["Window2BottomCenter", "Window3TopCenter"]});
instance.connect({uuids: ["Window2LeftMiddle", "Window4LeftMiddle"]});
instance.connect({uuids: ["Window4TopCenter", "Window4RightMiddle"]});
instance.connect({uuids: ["Window3RightMiddle", "Window2RightMiddle"]});
instance.connect({uuids: ["Window4BottomCenter", "Window1TopCenter"]});
instance.connect({uuids: ["Window3BottomCenter", "Window1BottomCenter"] });
//
//
// listen for clicks on connections, and offer to delete connections on click.
//
instance.bind("click", function (conn, originalEvent) {
// if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
// instance.detach(conn);
conn.toggleType("basic");
});
instance.bind("connectionDrag", function (connection) {
console.log("connection " + connection.id + " is being dragged. suspendedElement is ", connection.suspendedElement, " of type ", connection.suspendedElementType);
});
instance.bind("connectionDragStop", function (connection) {
console.log("connection " + connection.id + " was dragged");
});
instance.bind("connectionMoved", function (params) {
console.log("connection " + params.connection.id + " was moved");
});
});
JSPlumb.fire("jsPlumbDemoLoaded", instance);
})
}
}
</script>
<style>
.item{
height:50px;
width:50px;
background-color: red;
display: inline-block;
}
.demo {
/* for IE10+ touch devices */
touch-action:none;
}
.flowchart-demo .window {
border: 1px solid #346789;
box-shadow: 2px 2px 19px #aaa;
-o-box-shadow: 2px 2px 19px #aaa;
-webkit-box-shadow: 2px 2px 19px #aaa;
-moz-box-shadow: 2px 2px 19px #aaa;
-moz-border-radius: 0.5em;
border-radius: 0.5em;
opacity: 0.8;
width: 80px;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
text-align: center;
z-index: 20;
position: absolute;
background-color: #eeeeef;
color: black;
font-family: helvetica, sans-serif;
padding: 0.5em;
font-size: 0.9em;
-webkit-transition: -webkit-box-shadow 0.15s ease-in;
-moz-transition: -moz-box-shadow 0.15s ease-in;
-o-transition: -o-box-shadow 0.15s ease-in;
transition: box-shadow 0.15s ease-in;
}
.flowchart-demo .window:hover {
box-shadow: 2px 2px 19px #444;
-o-box-shadow: 2px 2px 19px #444;
-webkit-box-shadow: 2px 2px 19px #444;
-moz-box-shadow: 2px 2px 19px #444;
opacity: 0.6;
}
.flowchart-demo .active {
border: 1px dotted green;
}
.flowchart-demo .hover {
border: 1px dotted red;
}
#flowchartWindow1 {
top: 34em;
left: 5em;
}
#flowchartWindow2 {
top: 7em;
left: 36em;
}
#flowchartWindow3 {
top: 27em;
left: 48em;
}
#flowchartWindow4 {
top: 23em;
left: 22em;
}
.flowchart-demo .jtk-connector {
z-index: 4;
}
.flowchart-demo .jtk-endpoint, .endpointTargetLabel, .endpointSourceLabel {
z-index: 21;
cursor: pointer;
}
.flowchart-demo .aLabel {
background-color: white;
padding: 0.4em;
font: 12px sans-serif;
color: #444;
z-index: 21;
border: 1px dotted gray;
opacity: 0.8;
cursor: pointer;
}
.flowchart-demo .aLabel.jtk-hover {
background-color: #5C96BC;
color: white;
border: 1px solid white;
}
.window.jtk-connected {
border: 1px solid green;
}
.jtk-drag {
outline: 4px solid pink !important;
}
path, .jtk-endpoint {
cursor: pointer;
}
.jtk-overlay {
background-color:transparent;
}
/* ---------------------------------------------------------------------------------------------------- */
/* --- page structure --------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------- */
body {
background-color: #FFF;
color: #434343;
font-family: "Lato", sans-serif;
font-size: 14px;
font-weight: 400;
height: 100%;
padding: 0;
}
.jtk-bootstrap {
min-height:100vh;
display:flex;
flex-direction: column;
}
.jtk-bootstrap .jtk-page-container {
display:flex;
width:100vw;
justify-content: center;
flex:1;
}
.jtk-bootstrap .jtk-container {
width: 60%;
max-width:800px;
}
.jtk-bootstrap-wide .jtk-container {
width: 80%;
max-width:1187px;
}
.jtk-demo-main {
position: relative;
margin-top:98px;
display:flex;
flex-direction:column;
}
.jtk-demo-main .description {
font-size: 13px;
margin-top: 25px;
padding: 13px;
margin-bottom: 22px;
background-color: #f4f5ef;
}
.jtk-demo-main .description li {
list-style-type: disc !important;
}
.jtk-demo-canvas {
height:750px;
max-height:700px;
border:1px solid #CCC;
background-color:white;
display: flex;
flex-grow:1;
}
.canvas-wide {
margin-left:0;
}
.miniview {
position: absolute;
top: 25px;
right: 25px;
z-index: 100;
}
.jtk-demo-dataset {
text-align: left;
max-height: 600px;
overflow: auto;
}
.demo-title {
float:left;
font-size:18px;
}
.controls {
top: 25px;
color: #FFF;
margin-right: 10px;
position: absolute;
left: 25px;
z-index: 1;
display:flex;
}
.controls i {
background-color: #5184a0;
border-radius: 4px;
cursor: pointer;
margin-right: 4px;
padding: 4px;
}
li {
list-style-type: none;
}
/* ------------------------ node palette -------------------- */
.sidebar {
margin:0;
padding:10px 0;
background-color: white;
display:flex;
flex-direction:column;
border: 1px solid #CCC;
align-items: center;
}
.sidebar-item {
background-color: #CCC;
border-radius: 11px;
color: #585858;
cursor: move;
padding: 8px;
width: 128px;
text-align: center;
margin: 10px;
outline:none;
}
button.sidebar-item {
cursor:pointer;
width:150px;
}
.sidebar select {
height:35px;
width:150px;
outline:none;
}
.sidebar-item.katavorio-clone-drag {
margin:0;
border:1px solid white;
}
.sidebar-item:hover, .sidebar-item.katavorio-clone-drag {
background-color: #5184a0;
color:white;
}
/*
.sidebar button {
background-color: #30686d;
outline: none;
border: none;
margin-left: 25px;
padding: 7px;
color: white;
cursor:pointer;
}*/
.sidebar i {
float:left;
}
#media (max-width: 600px) {
.sidebar {
float:none;
height: 55px;
width: 100%;
padding-top:0;
}
.sidebar ul li {
display:inline-block;
margin-top: 7px;
width:67px;
}
.jtk-demo-canvas {
margin-left: 0;
margin-top:10px;
height:364px;
}
}
/* ---------------------------------------------------------------------------------------------------- */
/* --- jsPlumb setup ---------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------- */
.jtk-surface-pan {
display:none;
}
.jtk-connector {
z-index:9;
}
.jtk-connector:hover, .jtk-connector.jtk-hover {
z-index:10;
}
.jtk-endpoint {
z-index:12;
opacity:0.8;
cursor:pointer;
}
.jtk-overlay {
background-color: white;
color: #434343;
font-weight: 400;
padding: 4px;
z-index:10;
}
.jtk-overlay.jtk-hover {
color: #434343;
}
path {
cursor:pointer;
}
.delete {
padding: 2px;
cursor: pointer;
float: left;
font-size: 10px;
line-height: 20px;
}
.add, .edit {
cursor: pointer;
float:right;
font-size: 10px;
line-height: 20px;
margin-right:2px;
padding: 2px;
}
.edit:hover {
color: #ff8000;
}
.selected-mode {
color:#E4F013;
}
.connect {
width:10px;
height:10px;
background-color:#f76258;
position:absolute;
bottom: 13px;
right: 5px;
}
/* header styles */
.demo-links {
position: fixed;
right: 0;
top: 57px;
font-size: 11px;
background-color: white;
opacity: 0.8;
padding-right: 10px;
padding-left: 5px;
text-transform: uppercase;
z-index:100001;
}
.demo-links div {
display:inline;
margin-right:7px;
margin-left:7px;
}
.demo-links i {
padding:4px;
}
.jtk-node {
background-color: #5184a0;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
position: absolute;
z-index: 11;
overflow: hidden;
min-width:80px;
min-height:30px;
width: auto;
}
.jtk-node .name {
color: white;
cursor: move;
font-size: 13px;
line-height: 24px;
padding: 6px;
text-align: center;
}
.jtk-node .name span {
cursor:pointer;
}
[undo], [redo] { background-color:darkgray !important; }
[can-undo='true'] [undo], [can-redo='true'] [redo] { background-color: #3E7E9C !important; }
</style>
See the official article to integrate with VueJs:
https://docs.jsplumbtoolkit.com/toolkit/current/articles/demo-vue2.html

Nested loops in Less

I have some nested loops in Less.
It should create css rules for padding with 3 sizes and 4 direction.
Code sample:
#sizes: normal, small, large;
#size-normal: 1em;
#size-small: 0.8 * #size-normal;
#size-large: 1.2 * #size-normal;
.l-padding {
#directions: top, left, right, bottom;
.s(#i: length(#sizes)) when (#i > 0) {
.s((#i - 1));
.d(#j: length(#directions)) when (#j > 0) {
.d((#j - 1));
#dir: extract(#directions, #j);
#s: extract(#sizes, #i);
#size: "size-#{s}";
&_#{dir}_#{s} {
.l-padding-mixin(#dir, ##size);
}
}
.d();
}
.s();
}
I don't know where is the problem but it compile to many duplacates. However each independet loop do their job.
.l-padding_top_normal {
padding-top: 1em;
}
.l-padding_left_normal {
padding-left: 1em;
}
.l-padding_right_normal {
padding-right: 1em;
}
.l-padding_bottom_normal {
padding-bottom: 1em;
}
.l-padding_top_normal {
padding-top: 1em;
}
.l-padding_left_normal {
padding-left: 1em;
}
.l-padding_right_normal {
padding-right: 1em;
}
.l-padding_bottom_normal {
padding-bottom: 1em;
}
.l-padding_top_normal {
padding-top: 1em;
}
...
.l-padding_top_normal {
padding-top: 1em;
}
.l-padding_top_small {
padding-top: 0.8em;
}
.l-padding_left_small {
padding-left: 0.8em;
}
.l-padding_right_small {
padding-right: 0.8em;
}
.l-padding_bottom_small {
padding-bottom: 0.8em;
}
.l-padding_top_normal {
padding-top: 1em;
}
.l-padding_left_normal {
padding-left: 1em;
}
.l-padding_right_normal {
padding-right: 1em;
}
.l-padding_bottom_normal {
padding-bottom: 1em;
}
...
To many duplicates. Can any one help with this?
UPD
thanks to #Harry find solution:
.l-padding-mixin(#direction, #size: 1em) {
padding-#{direction}: #size;
}
#sizes: normal, small, large;
#size-normal: 1em;
#size-small: 0.8 * #size-normal;
#size-large: 1.2 * #size-normal;
//==== layouts ====
.l-padding {
#directions: top, left, right, bottom;
#i: length(#sizes);
#j: length(#directions);
.d(#j) when (#j > 0) {
.d((#j - 1));
#dir: extract(#directions, #j);
#s: extract(#sizes, #i);
#size: "size-#{s}";
&_#{dir}_#{s} {
.l-padding-mixin(#dir, ##size);
}
}
.-(#i) when (#i > 0) {
.-((#i - 1));
.d(#j);
} .-(#i);
}

LESS mixin: How to loop through passed in arguments

I usually write SASS, but for a particular project I have to use LESS.
How do I achieve something like the below using less? Using sass the mixin can be called like #include align(hcenter top) to position an element horizontally in the middle and to the top.
#mixin align($styles) {
position: absolute;
content: '';
display: block;
#each $style in $styles {
#if ($style == center) {
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
#if ($style == hcenter) {
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
#if ($style == vcenter) {
margin-top: auto;
margin-bottom: auto;
top: 0;
bottom: 0;
}
#if ($style == top) {
top: 0;
}
#if ($style == bottom) {
bottom: 0;
}
#if ($style == right) {
right: 0;
}
#if ($style == left) {
left: 0;
}
}
}
See Mixin Arguments, List Functions and Loops.
With a thing like "for" the snippet can be converted to something like:
#import "loops/for";
#usage {
.align(hcenter, top, bottom, etc);
}
.align(#styles...) {
position: absolute;
content: '';
display: block;
.for(#styles); .-each(#style) {
& when (#style = center) {
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
& when (#style = hcenter) {
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
& when (#style = vcenter) {
margin-top: auto;
margin-bottom: auto;
top: 0;
bottom: 0;
}
& when (#style = top) {
top: 0;
}
& when (#style = bottom) {
bottom: 0;
}
& when (#style = right) {
right: 0;
}
& when (#style = left) {
left: 0;
}
}
}
---
Actually above code can be optimized to more compact:
.align(#styles...) {
position: absolute;
content: '';
display: block;
.center(#pos) {
margin-#{pos}: auto;
#{pos}: 0;
}
.for(#styles);
.-each(center) {.-each(hcenter); .-each(vcenter)}
.-each(hcenter) {.center(left); .center(right)}
.-each(vcenter) {.center(top); .center(bottom)}
.-each(#style) when (default()) {#{style}: 0}
}
Though this way it may look more confusing for one not too familiar with Less.
I'm not sure about your each loop. For instance (center, top;) will set top: 0; twice?
But you can try:
.align(#styles){
.setproperties(#iterator:1) when (#iterator <= length(#styles)) {
#style: extract(#styles,#iterator);
& when (#style = center) {
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
& when (#style = hcenter)
{
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
// add more & when 's here
.setproperties((#iterator + 1));
}
position: absolute;
content: '';
display: block;
.setproperties();
}
The above can be called with:
selector1 {
.align(center;);
}
selector2 {
.align(center hcenter;);
}

Bootstrap collapse nav at 991px

Building a site using Bootstrap. Having an issue with the van. I want it to collapse at 991px. Searched online and found this code, however it has changed the function of the nav as the nav wont stay open. Any ideas? The code used to override default is in my custom.css
http://nurdit.com/styleengineered/
#media (max-width: 991px) {
.navbar-header {
float: none;
}
.navbar-toggle {
display: block;
}
.navbar-collapse {
border-top: 1px solid transparent;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
}
.navbar-collapse.collapse {
display: none!important;
}
.navbar-nav {
float: none!important;
margin: 7.5px -15px;
}
.navbar-nav>li {
float: none;
}
.navbar-nav>li>a {
padding-top: 10px;
padding-bottom: 10px;
}
}
Try changing the CSS above to:
#media (max-width: 991px) {
.navbar-header {
float: none;
}
.navbar-toggle {
display: block;
}
.navbar-collapse {
border-top: 1px solid transparent;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
}
.navbar-collapse.collapse {
display: none!important;
}
.navbar-nav {
float: none!important;
margin: 7.5px -15px;
}
.navbar-nav>li {
float: none;
}
.navbar-nav>li>a {
padding-top: 10px;
padding-bottom: 10px;
}
.navbar-collapse.collapse.in { /* NEW */
display: block!important;
}
}
As far as I can tell, this does the trick on your site. Credit for this suggestion goes to Dave Forber , see Bootstrap 3 Navbar Collapse