SASS: Can I get element count in one class? - css

I want to position divs next to each other spaced equally and reposition them if the window size is changed. For that I think I need SASS. One time there may be 14 divs, other 10 divs in one class and I want them to be spaced equally depending on the count and the screen size. Can I get element count in SASS for one class?

Or you can do that with pure css and flex property
.equalSpaces {
overflow: hidden;
display: flex;
}
.equalSpaces p {
padding: 5px;
margin: 0;
background-color: #000;
border: 1px solid #999;
}
.equalSpaces div {
display: inline-block;
flex: 1; /* to make all blocks equal */
}
An example: http://jsfiddle.net/LbxyLmpg/
edit: #cimmannon suggestion display: inline-block;

You just need to use jQuery for this. Not AJAX or SASS. The reason is, AJAX is server side and SASS is just precompiled CSS, nothing more. So, you need to make it this way:
$(document).ready(function(){
$(".equalSpaces").each(function(){
totalDivs = $(this).find("div").length;
$(this).find("div").width(100/totalDivs + "%");
});
});
Fiddle: http://jsfiddle.net/praveenscience/h72horvz/

Related

CSS How to achieve word cloud?

I'm trying to create a word cloud type output with only CSS. Basically, I have a div box and a X number of text elements which need to go inside the box. However, they need to be of different font size. For example, let's say I have this:
.box { display: flex; width: 40vw; height: 30vw; overflow: hidden; }
.text1 { font-size: 5vw; }
.text2 { font-size: 4vw; }
.text3 { font-size: 3.5vw; }
.text4 { font-size: 3vw; }
I can position the text elements inside the box but I have a few questions regarding the layout. My lack of thorough CSS knowledge prevents me from telling if this is possible at all with just CSS or not:
How can I avoid collision of the text elements?
How can I ensure they stay within the boundaries of the box?
I believe it's not possible to make Word Cloud using CSS only, you need to have Javascript function or lib like WordCloud2.js that handle element positioning.
Demo:
https://timdream.org/wordcloud/#wikipedia:Cloud
References:
https://github.com/timdream/wordcloud2.js
https://github.com/timdream/wordcloud

CSS/Jade/HTML: boxes won't inline properly

I have the following Jade template:
extends layout
block content
h2 Characters and Portraits
div(id="portraitsBox")
- var portraits = ["Clown-Fox", "Dragon-Bear", "Fish-Bear", "Deer-Wolf", "Salamander-Ant", "Side-Duck"];
for filename in portraits
- var url = "/images/portraits/" + filename.toLowerCase() + ".png"
div(class="characterBox" id=filename)
h3(class="characterName")= filename
img(class="portrait" src= url)
link(rel='stylesheet', href='/stylesheets/characters.css')
Which pulls from the following CSS:
#portraitsBox {
border: 1px solid black;
padding: 10px;
}
.characterBox {
position: relative;
padding: 5px;
border: 1px solid black;
width: 350px;
display: inline;
}
.characterName {
padding-top: 0px;
width: 150px;
font: Arial;
text-align: center;
}
This works fine if I take out display: inline, but every time I try put it back in I get this garbage:
http://www.orderofthemouse.co.uk/characters
And the container div resizes itself to 169.9px wide!!?
What's going on here? I checked with Firebug and it doesn't look like any of the Bootstrap default stylings are over-riding my own CSS (they're called in the extended layout file) or anything like that, and there's nothing in the cascade that should be causing it, to my reckoning. When I look at the generated HTML all the elements are nested as expected, which was my next consideration so it doesn't seem to be anything silly I overlooked...?
Do you want to get this result: http://screencast.com/t/c06yM3cr
I am confused because you said that it works fine if you disable display inline, and when I tried that they were still displaying as block.
If your desired result is what I have in the sceenshot, all you have to do is set the wrapper #portraitsBox to display: flex.

CSS calc() behaviour in CSS variables

I'm curious to the behaviour of using calc() in setting a CSS variable.
Example:
#test {
--halfWidth: calc(100% / 2);
}
Now, if the #test element, say a div, was 500px wide, I would like the --halfWidth variable to be set to 250px.
But, as far as I can tell the var(--halfWidth) code used elsewhere simply drops in the calc(100% / 2) string instead of 250px. Which means that I can't use the calculation of say element A and use it in element B later on, since it would simply set for example width: var(--halfWidth); as half the width of element B instead of half the width of element A, where the variable was defined.
I've scoured the web trying to find any documentation on the behaviour of this, but I have so far drawn a blank.
Ideally, setting a CSS variable using calc should be available in two variants:
One variant working just like this example, simply dropping in the string as-is, bar any in-string variable replacements.
A second variant where calc() would yield the result of the calculation instead of simply replacing the string.
How to achieve this? I'd rather leave the actual implementation to people suited to it, but one possibility would be an eval() kind of thing; like eval(calc(100% / 2)) would give the result 250px.
Anyway, if anyone have any real documentation on this behaviour or a solution to how to get the example above to yield the result instead, I'm all ears!
Edit: Just FYI, I have read the specs at https://drafts.csswg.org/css-variables/
This is kind of a tough question to answer cause the answer will not be:
Do it like this...then it will work
The problem you are facing is the normal behavior of CSS. It cascades the styles. If what you are trying to achieve would work it would get real messy after a short amount of time.
I mean how cool is it that you can define a variable like this
#test {
--halfWidth: calc(100% / 2);
}
where var(--halfWidth) should always be calc(100% / 2). Did you note that it will always be half the width of the parent element?
Imagine how strange it would be if a programmer in a few months reads your code and has box with a width of 1000px set with --halfWidth and now it is 250px wide ... I would think the internet is broken :) It should just be 500px wide.
To achieve what you want, you could/should define different vars defining the widths of the parent elements. And split it down to the children.
One approach to this is to dynamically add a line to the CSS Object Model (CSSOM) which explicitly declares the width of the .halfwidth class.
This width will then apply to all divs with the .halfwidth class.
In the example below, I have, additionally, made .element-a horizontally resizable, so that you can see more clearly that as you change the width of .element-a, the width of both .halfwidth divs changes proportionately, including the .halfwidth div which is a child of .element-b.
Working Example:
let myStylesheet = document.styleSheets[0];
const elementA = document.getElementsByClassName('element-a')[0];
let elementAWidth = window.getComputedStyle(elementA).getPropertyValue('width');
const calculateHalfWidth = (elementAWidth) => {
myStylesheet.insertRule('.halfWidth { width: ' + (parseInt(elementAWidth) / 2) + 'px; }', myStylesheet.cssRules.length);
}
calculateHalfWidth(elementAWidth);
// ================================================================================
// THE SCRIPT BELOW USES A ResizeObserver TO WATCH THE RESIZABLE .element-a DIV
// ================================================================================
const elementAObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.contentRect.width !== elementAWidth) {
calculateHalfWidth(entry.contentRect.width);
}
}
});
elementAObserver.observe(elementA);
body {
font-family: sans-serif;
}
div.element {
float: left;
width: 200px;
height: 100px;
margin: 12px 3px;
text-align: center;
border: 1px solid rgb(0, 0, 0);
}
div.element h2 {
font-size: 18px;
}
div.element-a {
resize: horizontal;
overflow: auto;
}
div.element-b {
width: 300px;
}
div.halfWidth {
height: 40px;
margin: 0 auto;
border: 1px dashed rgb(255, 0, 0);
}
div.halfWidth h2 {
font-size: 14px;
}
<div class="element element-a">
<h2>Element A</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>
<div class="element element-b">
<h2>Element B</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>

How to change height of ui-grid row?

I am using ui-grid. I have a lot of rows and that is why I use scrolling. Everything works perfectly ok until I try to change the height of the rows. Then the scrolling becomes a mess. I have added an example here http://plnkr.co/edit/S6ylwOVgcQp7CSsZZxpR?p=preview
This is one of the tutorials from the ui-grid website - the only thing I have changed is the CSS. I have added these rules.
.ui-grid-cell-contents {
padding: 1px 1px;
}
.ui-grid-render-container-body .ui-grid-header-cell,
.ui-grid-render-container-left .ui-grid-header-cell,
.grid .ui-grid-row,
.grid .ui-grid-cell,
.grid .ui-grid-cell .ui-grid-vertical-bar {
height: 22px !important;
font-size: 12px;
line-height: 20px;
}
.ui-grid-render-container-body .ui-grid-header-cell,
.ui-grid-render-container-left .ui-grid-header-cell,
ui-grid-header-cell {
height: 55px !important;
}
.ui-grid-filter-container {
padding: 1px 3px;
}
Scrolling works perfectly ok if the above CSS rules are removed.
So I either need to add more CSS rules or I need to use some API of the grid in order to set row height properly.
Any help will be much appreciated.
How do I change row height and keep scrolling smooth?
UPDATE:
Here is a comparison between a default grid and one with modified CSS:
http://plnkr.co/edit/x1nQGvpkY4bRMs9D09Ws?p=preview
try to scroll the rows up and down for each grid. The difference should be pretty obvious.
Take out the:
height: 22px !important;
from the css and add:
rowHeight:22
to the gridOptions.
I have the feeling that this is much smoother.
Forked Plunker
scope.gridOptions = {
rowHeight: 33
}
The best way of changing the row height is from the grid options.
Try add this to your css:
.ui-grid-viewport .ui-grid-cell-contents {
word-wrap: break-word;
white-space: normal !important;
}
.ui-grid-row, .ui-grid-cell {
height: auto !important;
}
.ui-grid-row div[role=row] {
display: flex ;
align-content: stretch;
}
Just alter grid class accordingly.
.grid{
height: 70vh;
}

Programmatically scroll ng-repeat with overflow:hidden

I'm using the following markup (JADE) to build a pagination with AngularJS and Foundation.
ul.pagination
li.arrow: a «
li(ng-repeat="month in months | orderBy:'_id'" ng-class="month._id === shownMonth ? 'current' : ''")
a(ng-href="#/months/{{month._id}}") {{ month._id | monthid:'short' }}
li.arrow#right-arrow: a »
In the CSS, I've set overflow: hidden. This gets me this:
Perfect so far, but obviously this could get long.
How can I make this scroll when the user clicks on the little arrow symbols at the end?
I've tried doing stuff like $(...).animate({left: '-=20'}) but it simply gets ignored (I'm guessing because of the Foundation css). Any ideas?
UPDATE
I've got a semi-working solution, but it's ugly.
I have attached an ng-show condition to the repeated list items as such:
li(ng-repeat="month in months | orderBy:'_id'" ng-class="month._id === shownMonth ? 'current' : ''" ng-show="month._id >= min && month._id <= max")
and after loading my data I do
$timeout(function() {
var availableWidth = $('ul.pagination').width() - 2 * $('ul li.arrow').width();
var itemWidth = $('li:not(.arrow)').width();
var total = Math.floor(availableWidth / itemWidth);
$scope.min = $scope.shownMonth - Math.floor(total / 2);
$scope.max = $scope.shownMonth + Math.floor(total / 2);
});
Then I basically just need to adjust min and max in an ng-click handler for the arrow buttons. This works, more or less, but for some reason, availableWidth gets calculated to much, much smaller than the space that's actually available for it - it's off by about 600px! Why?
Animating the left position makes no sense. What you want to animate is the horizontal scroll position (element.scrollLeft).
Also, consider removing your arrows out of the list of months. They don't make sense semantically in that list, and they'll end up constraining you when you want to scroll just the months but leave the arrows in place.
Edited to add fiddle: http://jsfiddle.net/R9QcB/5/ I did this with jQuery for quickness, but scrollLeft is a native javascript property.
It's the CSS that's actually important here moreso than the javascript:
#pagination {
text-align: center;
}
.nav {
display: inline-block;
vertical-align: middle;
}
ul {
display: inline-block;
vertical-align: middle;
max-width: 75%;
overflow: hidden;
white-space: nowrap;
}
li {
display: inline-block;
list-style: none;
color: #fff;
background: #aaa;
padding: 0.25em 0.5em;
margin: 0 0.5em;
}
Basically, you need a containing element that you can update the scrollLeft position of. That containing element has an overflow: hidden on it so that its child elements sit in a series inside the container (which is a result of white-space: nowrap).

Resources