I've a rather complicated website design I'm working on. I have the following 4 containers (I call them that, but they don't have the .container class)
In a wide screen layout:
In a narrow screen layout:
The issue I'm having is matching the total height of the white, grey and yellow containers with the blue container on a wide screen layout:
The grey and yellow containers are in a .row div, so adding the style { display: inline-flex } makes them the same height on a narrow screen layout:
However, this moves them completely to the side in the wide screen layout and this wouldn't match the combined white, grey and yellow containers with the blue container:
I tried a JavaScript solution as #Paulie_D recommended.
$(window).load(function () {
NormalizeHeights();
});
window.onresize = function (event) {
NormalizeHeights();
}
function NormalizeHeights() {
if (window.innerWidth >= 768) {
var carousel = $(".carousel-container");
var dashTop = $(".dash-row-top");
var panelLeft = $(".dash-row-bottom .panel-lightgray");
var panelRight = $(".dash-row-bottom .panel-yellow");
var carouselHeight = parseFloat(carousel.css('height'));
var dashTopHeight = parseFloat(dashTop.css('height'));
var panelLeftHeight = parseFloat(panelLeft.css('height'));
var panelRightHeight = parseFloat(panelRight.css('height'));
var dashBottomHeight;
if (panelLeftHeight > panelRightHeight) {
dashBottomHeight = panelLeftHeight;
}
else {
dashBottomHeight = panelRightHeight;
}
if (carouselHeight > (dashTopHeight + dashBottomHeight)) {
var difference = carouselHeight - (dashTopHeight + dashBottomHeight);
panelLeft.css("height", (dashBottomHeight + difference));
panelRight.css("height", (dashBottomHeight + difference));
}
else {
var difference = (dashTopHeight + dashBottomHeight) - carouselHeight;
carousel.css("height", (carouselHeight + difference));
panelLeft.css("height", (dashBottomHeight));
panelRight.css("height", (dashBottomHeight));
}
}
}
This works, sort off, but it's extremely unlikable in my estimation.
I had a similar problem and the solution I found was rather ugly but worked for me.
I used divs that would clear formats BUT would their presence would be conditioned (using ng-if). Programmatically, I measured the width of the screen and set a threshold. If the width was above the threshold, I set the location of the divs, measured the height of the contents and, when applicable, forcefully changed the height of all the relevant divs to look the same (note that you would need to set this size update AFTER A TIMER is fired to let the rendering to complete).
Hope this gives you some ideas and remember: I was the first to call this ugly.
Related
I have a responsive app for desktop and mobile.
In the app i have a div which randomly shows texts of all kinds of lengths.
I want to do the following:
If the line breaks because the length of the text is too wide for the width of that div, i want the font-size to reduce itself (I am using em's in my app).
Is it something i need to build directive for it? is it something that was built and used wildly?
Writing a robust solution for this problem is going to be non-trivial. As far as I know, there's no way to tell whether a line of text breaks. However, we do know the criteria for line breaking is the width of the text being wider than the element, accounting for padding.
The Canvas API has a method called measureText which can be used to measure a string, using a given context with a font and size set. If you spoof the settings of the element with a canvas, then you can measure the text with the canvas and adjust the size until it fits without overflowing.
I've written up a rough implementation of the way I would tackle this.
function TextScaler(element) {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
var scaler = {};
scaler.copyProps = function() {
var style = element.style.fontStyle,
family = element.style.fontFamily,
size = element.style.fontSize,
weight = element.style.fontWeight,
variant = element.style.fontVariant;
context.font = [style, variant, weight, size, family].join(' ');
};
scaler.measure = function(text) {
text = text || element.innerText;
return context.measureText(text);
};
scaler.overflows = function() {
var style = window.getComputedStyle(element),
paddingLeft = style['padding-left'],
paddingRight = style['padding-right'],
width = style.width - paddingLeft - paddingRight;
return scaler.measure() > width;
};
scaler.decrease = function() {
// decrease font size by however much
};
scaler.auto = function(retries) {
retries = retries || 10;
if(retries <= 0) {
scaler.apply();
console.log('used all retries');
}
if(scaler.overflows()) {
scaler.decrease();
scaler.auto(retries - 1);
} else {
console.log('text fits');
scaler.apply();
}
};
scaler.apply = function() {
// copy the properties from the context
// back to the element
};
return scaler;
}
After you've sorted out some of the blank details there, you'd be able to use the function something like this:
var element = document.getElementById('');
var scaler = TextScaler(element);
scaler.auto();
If it doesn't manage to decrease it within 10 retries, it will stop there. You could also do this manually.
while(scaler.overflows()) {
scaler.decrease();
}
scaler.apply();
You'd probably want some fairly fine tuned logic for handling the decrease function. It might be easiest to convert the ems to pixels, then work purely with integers.
This API could quite trivially be wrapped up as a directive, if you want to use this with Angular. I'd probably tackle this with two attribute directives.
<div text-scale retries="10">Hello world</div>
Of course, if it's not important that all the text is there onscreen, then you can just use the text-overflow: ellipsis CSS property.
I have a KPI dashboard with a lot of small charts. One type of chart is in fact a HTML table. It is displayed in a DIV.
<div style="width:400px; height:250px;overflow:hidden">
<table>
<tr><th>Col1</th><th>Col2</th></tr>
<tr><td>Row1</td><td>Row2</td></tr>
</table>
<div>
Currently, I hide the overflow. I would like to make the table 'fit' the div.
How can I make this table to fit/scale down to the DIV if it would become too big to diplay? Ideally, the text would also shrink.
This CSS will make your table have the same height/width as the container you are using. Borders/background are only added for visualising what happens.
Shrinking the text will however be far more challenging. There is probably no way without using javascript to achieve that. And even if you did, content might end up being unreadable because of a too small font-size.
I managed to come up with some javascript/jquery code to change the font-size until the table fits the div or the font-size reaches 5px (= unreadable). Of coarse you will need to edit some of it yourself (because it would apply on all tables if you don't change the selectors to id's)
[JSFiddle]
table{
width: 100%;
background-color: red;
}
th, td{
width: 50%;
border: blue solid 1px;
}
Jquery / Javascript
$(document).ready(function () {
var HeightDiv = $("div").height();
var HeightTable = $("table").height();
if (HeightTable > HeightDiv) {
var FontSizeTable = parseInt($("table").css("font-size"), 10);
while (HeightTable > HeightDiv && FontSizeTable > 5) {
FontSizeTable--;
$("table").css("font-size", FontSizeTable);
HeightTable = $("table").height();
}
}
});
Here is what I use currently, it is embedded in a project (see for example the classes), but feel free to use it as inspiration.
scaleTable = function (markupId) {
//This hacky stuff is used because the table is invisible in IE.
function realWidth(obj){
var clone = obj.clone();
clone.css("visibility","hidden");
$('body').append(clone);
var width = clone.outerWidth();
clone.remove();
return width;
}
function realHeight(obj){
var clone = obj.clone();
clone.css("visibility","hidden");
$('body').append(clone);
var height = clone.outerHeight();
clone.remove();
return height;
}
var table = $("#"+markupId+" table:first-of-type");
var tablecontainer = $("#"+markupId).parents( ".scalabletablecontainer" );
var scalex = tablecontainer.innerWidth() / realWidth(table);
var scaley = tablecontainer.innerHeight() / realHeight(table);
var scale = Math.min(scalex, scaley);
if (scale<1.0) {
var fontsize = 12.0 * scale;
var padding = 5.0 * scale;
$("#"+markupId+" table tbody").css("font-size", fontsize + "px");
$("#"+markupId+" table tbody TD").css("padding",padding + "px");
$("#"+markupId+" table TH").css("padding",padding + "px");
}
};
Get table and div dimensions as shown in the previous comments. Then apply css
transfrom:scale(factorX, factorY)
to the table.
I want to have to floated columns side-by side. If second column has contents then the first column should resize its content based on the second column, is that possible with CSS? Widths are not defined.
It's possible using javascript but not with straight CSS. Here are some ways to do it:
Using javascript:
var rightDiv = document.getElementById("straightJ2");
var rightWidth = rightDiv.clientWidth;
var leftDiv = document.getElementById("straightJ1");
if($('#straightJ2').text() || rightDiv.hasChildNodes()) {
leftDiv.style.width = rightWidth + "px";
}
Or more minimal (and possibly overwhelming/hard to follow) javascript:
if($('#minimal2').text() || $('#minimal2').firstChild) {document.getElementById("minimal1").style.width = document.getElementById("minimal2").clientWidth + "px";}
Using jQuery:
if($('#secondColumnId').html() != '')
{
$('#firstColumnId').width($('#secondColumnId').width());
}
Each of these check the second div for text or a child element and change the width of the first if one of those conditions is met
All examples can be found used in this jsFiddle
Is there a way to autosize HTML table height based on content? Also if it's a cell (or cells) next to a neighbor cell with multiple rowspans.
E.g. if I have a table like this (cell on the right has Rowspan="2" and height of the cell content = 600px, in each cell on the left height of the cell content = 150px):
there is a gap between 2 cell consents on the left because cells themselves autosized their height. I'd like it to look like this:
Where top cells automatically collapse to cell content height. Is there anyway to achieve this?
This sets the last row of cells to the correct height (demo):
function grow(td) {
var table, target, high, low, mid;
td = $(td);
table = td.closest('table');
target = table.height();
low = td.height();
// find initial high
high = low;
while (table.height() <= target) {
td.height(high *= 2);
}
// binary search!
while (low + 1 < high) {
mid = low + Math.floor((high - low) / 2);
td.height(mid);
if (table.height() > target) {
high = mid;
} else {
low = mid;
}
}
td.height(low);
}
$('tr:last-child td').each(function() { grow(this); });
It should be trivial to convert this into plain JavaScript.
Update: For more complicated tables, you'll want to replace the last line with this (demo):
$.each($('td').get().reverse(), function() { grow(this); });
The idea is to call grow() on every cell, starting with the last row and working upwards.
considering table id="mytable" it would be:
$("#mytable").find("td").each(function(){
var ContentHeight = $($(this).html()).height();
$(this).height(ContentHeight);
});
at the end of the your page create a javascript code and let it do it for you:
<script type="text/javascript">
document.getElementById("idOfTd").style.height="100px";
</script>
I think it better create like this http://jsfiddle.net/miqdad/w9QYB/
I have this html:
<div id="subNav"></div>
<div id="feed"></div>
<div id="feedBar"></div>
I have floated all of these divs left. I set the width of #subNav and #feedBar, but on #feed I set its min-width . It takes the min-width even though the window is larger. Is there any way that with floating you can make the min-width work? I am trying to make a flexible layout on the page.
The following answer uses a JavaScript solution, in response to #Chromedude's comment (to the original question):
#David Is there any way to override this behavior? with javascript?
I'm sure there's a far more simple way of doing this (certainly with a JavaScript library), but this was the best I could come up with at this time of morning (in the UK):
var feed = document.getElementById('feed');
var width = document.width;
var feedBarWidth = document.getElementById('feedBar').clientWidth;
var subNavWidth = document.getElementById('subNav').clientWidth;
feed.setAttribute('style', 'width: ' + (width - (subNavWidth + feedBarWidth)) + 'px');
JS Fiddle demo.
Using jQuery (just as a suggestion as to the ease offered by a library):
var bodyWidth = $(document).width();
var subNavWidth = $('#subNav').width();
var feedBarWidth = $('#feedBar').width();
$('#feed').css('width', bodyWidth - (subNavWidth + feedBarWidth));
Use a grid system such as the one in Foundation 3. When placed on a div representing an element of the grid, min-width behaves just fine.
To get min-width to work without a grid, use a CSS rule that inserts an invisible pseudo-element with the desired minimum paragraph width.
p:before {
content: "";
width: 10em;
display: block;
overflow: hidden;
}
Further details are at the source where I learned this.