i have the following structure :
root grid
grid1
grid2
grid3
I define the columns : repeat(5 1fr)
the problem is that because the content they have different widths.
Is there a way somehow to pick the largest element width and set it as min-width to the other 2 grids.
Something like this /pseudo code/:
repeat(5 minmax(max(grid1.cells.width,grid2.cells.width,grid3.cells.width)), 1fr))
or in case i know which grid will be widest :
repeat(5 minmax(grid2.cells.width, 1fr))
this is very hacky non automatic solution:
let min_width = window.getComputedStyle(grid2.children[0]).width
grid1.style.gridTemplateColumns = `repeat(${grid1_ncols}, minmax(${min_width}, 1fr))`
a better one ??
Related
See this fiddle.
Consider a grid of words in four columns, with each column being the same width. I can get this with grid-template-columns: repeat(auto-fill, minmax(25%, 1fr)); Most of the time, these will be short words. But there could be a long word which overflows its block:
If this were static data, I could have just changed the grid css to grid-template-columns: repeat(auto-fill, minmax(33%, 1fr)); to comfortably fill the space:
How can I make the CSS renderer adjust the number of columns for me, making each the same width, using the width of the widest word block in the set?
I'm surprised that CSS doesn't (as far as I can tell) support this since I think it should be a common use case for wrapping grids. I tinkered until I had a solution with a minimal amount of javascript:
example fiddle with IIFE
First, we need to find out how wide the widest string (or could be any block element) will be when rendered on the client. grid-template-columns: repeat(1, max-content); will do that by arranging the elements in a single column, and all elements get the width of the widest one. After the dimensions are established but before being rendered to the screen, grab any element, compute the number of columns that will fit, then change the CSS for the container to have that many columns + 1fr to make them fill the space:
(function(){
const ul = document.querySelectorAll('ul')[0];
const ee = [...document.querySelectorAll('li')];
const max = ee.map(e=>e.offsetWidth).reduce((a,b)=>Math.max(a, b));
const cols = Math.min(5,Math.floor(ul.offsetWidth/max));
ul.style.gridTemplateColumns = "repeat("+cols+", 1fr)";
})();
This seems to work with no flicker in all evergreen browsers. Angular version I used:
ngAfterViewInit(): void {
const ul: HTMLElement = this.ul.nativeElement;
let cols: number = 0;
const w: number = ul.children[0].clientWidth;
if (w > 0) {
cols = Math.min(5, Math.floor(ul.offsetWidth / w));
}
ul.style.gridTemplateColumns = "repeat(" + cols + ",1fr)";
}
As far as I know this is unsolvable with CSS-only, so, I will provide a Javascript-based solution.
First of all, let's find the longest text:
let longestText = '';
for (let text of texts) {
if (longestText.length < text.length) longestText = text;
}
Then, you can find that item:
let lng = document.querySelectorAll('ul li').filter((item) => item.innerText === longestText)[0].offsetWidth;
Then you can divide the whole width that you have at your disposal with lng, the value you have just calculated and see how many columns you can have.
SHORT VERSION/CLARIFICATION
The gist of my question would be, assuming each value was unique to it’s context, would it possible to use undefined variables in sass, similarly to an algebraic function.
[formula for height of “.page-wrapper” div]
a * 0.75 = b
[formula for height of nested/child “sticky-vert” div]
b * 4 = c
a=the base value
b=the calculated value of the parent element
c=the calculated value of the child element
…and so and so forth
Most of the #mixins and #extend functions I’ve seen in sass have to do w/ overriding or replacing a display value like color or margin but not actually using calculations to get a new value from an "undefined" variable.
LONG VERSION
I have an SCSS document and I'm trying to take the numeric value from one class to use as the base for another class. Basically, I'm trying to take the height calculated from the parent class (".page-wrapper") to use as the base variable for it's child (".sticky-vert"). Is this possible to do, solely w/ sass and without javascript modifiers?
For what it's worth the website itself is set to horizontal scroll (except for the 1 section, explained below) and all the ".page-wrapper" element is set to display:flex along w/ its children. I want the child element to have four times the height as it's parent to accommodate for 4 diff content items within that section.
1. Here are the values set at the top of my scss doc:
/*Base Variables*/
$height: 100vh; // *the default value for height*
$width: 100vw; // *the default value for width*
2. These are the calculations for the parent container(s), using the $height value:
.header {height: $height * 0.14} // *header is 14vh, remains static / never scrolls*
.page-wrapper {height: $height * 0.75} // *page-wrapper is 75vh. This is a div container between the header and footer for the main content, this is the only area of the page that moves*
.footer {height: $height * 0.11} // *footer is 11vh, remains static / never scrolls*
Imagine it like a hamburger style webpage with only the middle moving.
3. This is the new value I want to calculate, without using JS modifiers or the actual numbers for flexibility:
.sticky-vert {height: height of ".page-wrapper" * 4} // Technically, the formula would be 75vh * 4 = 300vh but...
I don't want to plug the actual numbers in, in case I change the values later on down the line and have to plug in the new numbers again. Also while sticky-vert {height: $height * 0.75 * 4} could work it still requires plugging in the then-assumed value of the parent's height (75vh).
HTML SAMPLE:
<header class="colors-1">header text, etc etc</header>
<div class="page-wrapper dark">
<section class="sec-1">THE PAGE SCROLLS HORIZONTALLY</section>
<section class="sec-2">UP UNTIL YOU REACH THE NEXT SECTION</section>
<section class="sec-3 sticky-vert">
<div id="vert-1">WHICH THEN SCROLLS VERTICALLY, STARTING W/ THIS DIV</div>
<div id="vert-2">THEN IT SCROLLS DOWN TO THIS ONE.</div>
</section>
<section class="sec-4">NOW ITS BACK HORIZONTAL</section>
<section class="sec-5">AND FINISHES HERE.</section>
</div>
<footer class="colors-1">footer text, etc, etc</footer>
If I'm following correctly, you may not need to do all these calculations. Instead, would it be possible to add the height values for the header and footer regions, and have them set to position: fixed;, which would lock these elements in place which you could set with top: 0;, et.al. Then the page wrapper (for the moving content) could have margins or padding set (depending on how the main content moves around) to offset from the header and footer regions. This method could avoid a number of calculations, allowing freedom for focusing on the other areas.
I am also trying to positioning a node in a cell in grid layout as below
layout: { name: 'grid',
fit: true, // whether to fit the viewport to the graph
rows:5,
columns:12,
padding: 10, // the padding on fit
position: function( node )
{ console.log("Row : "+node.data('row') + ", COL : "+node.data('col'));
return {row:3, col:node.data('col')};
}
},
But node is always created in the middle of the canvas, even if I hardcode the row as above. Any suggestion, what is going on.
Thank you
If you're manually specifying positions, you shouldn't need to set the overall dimensions. Maybe you've overconstrained it (e.g. row beyond rows)?
Alternatively, you could set the dimensions and a sort function to indicate the ordering.
I have an instance of TabLayoutPanel where number of tabs would be set dynamically. Therefore to align tabs to fill whole width of the screen I need to
1) Override gwt-TabTayoutPanel default value width 16384px with auto !important (done);
2) Set width of gwt-TabTayoutPanelTab to proper percentage value (e.g. 2 tabs = 50%. 3 tabs = 33%, 4 tabs = 25% and so on).
I have a simple function for that which goes like this (simplified):
Double cssValue = 100.0/getWidgetCount();
(done)
3) Now here goes my question: how can i set the width of gwt-TabTayoutPanelTab from Java? I bolded Tabs because when i use this.getStyleName(); i got in return gwt-TabLayoutPanel not gwt-TabLayoutPanelTab .
In sum, I can divide my question in two:
-how to access TabLayoutPanelTab css class from GWT?;
-how to set said class width with my dynamically generated percentage number?;
EDIT:
Proper edit of function to determine percentage value.
-how to access TabLayoutPanelTab css class from GWT?;
int widgetCount = panel.getWidgetCount();
for(int i = 0; i < widgetCount; i++)
System.out.println(panel.getTabWidget(i).getParent().getStyleName());
}
As you can see there is no direct way to access the tabs. What you can do is access the widgets in the tabs, and get their parent, which is the tab in question.
-how to set said class width with my dynamically generated percentage number?;
If you have a certain amount off possible percentages then you can declare those classes (e.g. custom-Width-25, custom-width-33 etc.) where you specify the width with the !important annotation in order to override everything else.
If the previous solution is not acceptable then you can only use inline css. This means that the element must be already loaded in the DOM. Somewhere in your code where you know that the element is loaded you can call something like this :
int widgetCount = panel.getWidgetCount();
for(int i = 0; i < widgetCount; i++) {
com.google.gwt.user.client.Element tabElement = panel.getTabWidget(i).getParent().getElement();
tabElement.getStyle().setWidth(100/widgetCount, Unit.PCT);
}
I'm looking for a way to have a HTML container fit the width of one of its children.
OK I know, this is how it already works by design.
But! I also need another children to collapse with a "text-overflow: ellipsis". Problem is: to apply such a property, you need this children to be in "display: block" mode, which makes it enlarge the container width.
Is there any secret time to achieve what I'm looking for.
Here is a JsFiddle in case you don't get it or want to give it a try.
Edit : by the way, and this is important, I'm targetting specifically Internet Explorer 10.
As watson said, there is no "shrink-to-fit" css rule. So, you have two choices:
Set the size of the .overflow elements manually and statically. So, instead of width:100%, you put width:330px.
Use javascript to resize the .overflow elements dynamically. (I'm assuming you have more than one.) You said you wanted to shrink to the biggest internal div. Let's say you have several divs you might want to shrink to, but you want to shrink to the largest of them. First, you set them all to a class like this:
.good-width{
border: solid 2px salmon;
width:auto; /* necessary for some browsers' offsetWidth */
display:inline-block; /* gives it the width of the contents */
}
And you put javascript something like this at the top of the page:
var goods = document.getElementsByClassName('good-width');
//collect the widest one's width
var maxwidth = 0;
for(var x = 0; x < goods.length; x++) {
if(goods[x].offsetWidth > maxwidth) {
maxwidth = goods[x].offsetWidth;
}
}
//set the width of the overflow divs to match
var overflows = document.getElementsByClassName('overflow');
for(var y = 0; y < overflows.length; y++) {
overflows[y].style.width = maxwidth + 'px';
}
If I misunderstood, and you're trying to match specific overflows to specific good-widths, you should assign each element an id and do things that way:
document.getElementById('overflowID').style.width = document.getElementById('good-widthID').offsetWidth + 'px';
If it were my website, I would actually combine both #1 and #2, in order to have it look at least decent for those who don't have javascript. That is, you set a static width to the overflow things that isn't too far off, then allow the javascript to overwrite it if it can.