I have container, which is re-sizable and contains inner elements <div>, which can be placed in any order and I can add them to container any amount when amount of them rising, the become smaller. My goal is when inner divs height or width, becomes smaller than 100px then automatically re-size container.
There can be more than one element smaller than 100px. When container re-sizes, all elements become bigger depending of percents of their width.
Problem: when there is more than one small element, they send many events to container, I want to send one request to container to re-size if there is possibility that it is enough to make all element enough size.
I tried to watch width, but it sends to many requests.
scope.$watch(function () {
return element.width();
}, function (oldval, newval) {
clearTimeout(containerCtrl.resizedFinished);
containerCtrl.resizedFinished = setTimeout(function () {
console.log("New Value=" + newval);
if (newval < 100)
scope.resizeContainer(element.width());
}, 100);
});
Maybe someone can give me any suggestions?
I use Angular, jquery base module, js.
I think you try to achieve:
draggable components should be minimum of 100px wide
when you drag/drop component into container, all components should shrink, so that they fit inside container
when components cannot get any smaller, container should grow (with 100px for each added component)
Sounds like you could get the styling done with flexbox in css:
.container {
display: inline-flex;
flex-direction: row;
padding: 2px;
min-width: 500px;
height: 120px;
background-color: yellow;
}
.component {
background-color: grey;
flex: 0 1 200px;
min-width: 100px;
height: 50px;
margin: 2px;
}
That way you do not have to do any watching of components through jQuery.
If the components also should have variable height, and container can have multiple rows, things become trickier. Then you need to be more specific about constraints.
EDIT:
If you cannot use flexbox for IE9, then try:
add event listener to component being dropped inside container (not on resize of individual components)
check (read from DOM) how many components are in container
if (container width - (component width * old number of components)) < 100
then shrinking is not allowed, so expand container
else
loop over each component to shrink them
Related
I want the table height to fit the parent’s available height. Ideally, I want:
The footer to always be docked at the bottom of the parent container.
If the table contains a few rows, the footer should remain docked at the bottom.
If the table contains more rows than fit the parent’s height and needs to overflow then the overflow should be visible only for the table body, and the footer should remain docked at the bottom and not be pushed downwards.
A flexbox approach if possible (it seems to me that this is a flex scenario)
What I don’t want:
A height: 100vh approach
A calc (100vh - ***px) involved (because I want to use the methodology in arbitrary component hierarchies inside my solution)
Fixed heights in the table
To use absolute/fixed positioning
No 3rd party solutions (if possible)
To use .offsetHeight
Example: https://stackblitz.com/edit/react-8h5dpy
Visual Examples:
Growing an item to take all available space but not exceeding the height of the parent could work like follows:
.parent {
// use flexbox layout for children
display: flex;
flex-direction: column;
}
.childThatGrows: {
// take as much space as available
flex-grow: 1;
// don't take more space than available (elements are as high as their content by default)
min-height: 0;
overflow: scroll;
}
Why min-height: 0? See https://stackoverflow.com/a/36247448/3066632.
For your example this might look like this: https://stackblitz.com/edit/react-wgbzpb.
I have responsive navigation menu and item blocks. Item blocks automatically adjusts their width as screen resolution changes(this is great). But navigation menu is in different section of page markup and don't receive the same width values as item blocks.
My goal: When resolution changes - script checks width of item block and then changes width of navigation menu to the same value.
So far I have:
$(document).ready(function(){
$( window ).resize(function() {
Resized();
});
});
function Resized()
{
var block_width= $(".block_item").width();
var width_to_set = parseInt(block_width);
$(".header-navi-inner").css({
'width': (width_to_set + 'px')
});
};
When I resize I can see that script executes and navigation menu changes width, but the width is not exactly the same as item block has. It is very close but it is wider for about 1px-5px based on what resolution is set.
For example:
When I looked in to CSS of these elements I found that item block has such styling:
float: left;
border-radius: 2px;
margin: 2px .25%;
position: relative;
width: 49.5%;
line-height: 0.8;
I believe margin .25% is causing issues because margin percentage value is calculated based on parent node. So when resolution changes parent node changes its size and also margin. That is why 1-5px difference occurs to my script?!
Is it true? How can I get exact width of element without any other added pixels?
What I have also tried:
$(".item").innerWidth();
$(".item").outerWidth(true);
But results were the same.
What I have also tried 2 (UPDATE):
I also tried to calculate margin value and then subtract it from width_to_set value:
var parent_node = $(".twelve").width();
var margin= (main_slaider * 0.0025);
var width_to_set = parseInt(column_width) - margin;
But still navigation menu was wider than item blocks for 1-3px
Thanks in advance for any help.
Let’s say I have a title in h1 element (any element would do). Its content is dynamic (do not know length of the title). It is supposed to be displayed in one line. h1 is in a DIV (let’s call it a container) of limited size.
How do I know if element (h1) overflows its container (DIV)?
So that if it overflows I would apply a CSS class to deal with the situation. For example I would scroll hidden content of h1 into view.
Width of the container is defined as relative to the screen size.
Example:
#container {
width: 60%;
background-color: gray;
height: 50px;
// overflow: hidden;
position: relative;
}
h1 {
overflow: hidden;
height: 100%;
margin: 0;
line-height: 50px;
}
<div id="container">
<h1>a soft white or grey mineral consisting of hydrated calcium sulphate. It occurs chiefly in sedimentary deposits and is used to make plaster of Paris and fertilizers, and in the building industry.</h1>
</div>
Best solution would be if it could be used in: primary in ngIf, secondary in ngClass directives, but any of following technologies are also good: Javascript, AngularJS, CSS, AngularJS directive.
Assuming jquery you could check widths of the elements.
if ($('h1').scrollWidth > $('#container').innerWidth()) {
//overflown
}
Here is my solution in AngularJS directive. It does not rely on parent element:
var myDirective = angular.module('myDirective', []);
myDirective.directive( 'myDirective' , ['$timeout' , function($timeout) {
return {
link: function (scope , element , attrs) {
// Wait few milliseconds until element is re-rendered
// so that element properties reflect content size.
$timeout( function(){
if (element[0].scrollWidth > element[0].offsetWidth){
// overflow
}
}, 200); // $timeout
} // link
}; // return
}]); // myDirective
Usage example:
<h3 my-directive>Hello World!</h3>
Note: Parent element must have restricted size otherwise it will adjust to the content and element will never overflow.
Code
Demo
The basic form of HTML looks like this:
<div class="home">
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<!-- blah, blah, blah! -->
</main>
</div>
</div>
W.r.t the HTML, I am trying to make the element #main fill the entire height of the browser viewport using JavaScript/jQuery like so:
jQuery(document).ready(function($){
// get height of browser viewport
var window_h = $(window).height();
// get height of the jumbotron, i.e. element #main
var jumbotron_h = $('.home #main').outerHeight(true);
// calculate necessary padding (top/bottom) to apply on #main so that the
// element's height is equal to that of the browser's viewport,
// and its contents are centered vertically
if (window_h > (jumbotron_h + 60)) {
var jumbotron_padding = (window_h - jumbotron_h)/2
} else {
var jumbotron_padding = 30
}
// apply calculated padding on the element dynamically
$('.home #main').attr('style', 'padding-top:'+jumbotron_padding+'px;padding-bottom:'+jumbotron_padding+'px;');
});
As clearly explained in the comments in the code above, the code automatically calculates the necessary padding to be applied on #main so that its height is equal to that of the browser's viewport.
It works well, except, the calculated padding (and therefore the resultant height) is wrong in one case that I was able to identify.
Easily reproducible at least on Windows 7, Google Chrome browser (latest) when you resize the browser window to 567x724 px, which implies 551x611 px viewport size, (you can use an extension like Window Resizer), you'll notice that the element's calculated padding results in its height being larger than that of the browser's viewport.
Why is this happening? I wasn't able to reproduce the same at any other resolution. What could I possibly be missing here?
First off, Jquery's .outerheight() function includes padding, which means that when you measure the height of your #Main element after this function runs the first time, it will equal the window.height. In other words - it will look awful when you resize your browser. You can see this in action on this fiddle when you resize the browser window the old-fashioned way. You can use margins instead, but then you'll have to adjust your CSS quite a bit. Even then, resizing the window still looks awful and buggy and has inconsistent results across browsers. You can see that on this fiddle.
The specific bug you're referring to is probably due to inconsistent math when you resize your window - a combination of your use of padding (which is included in .outerheight() as mentioned above) and the viewport size not being easily divisible by 2 (it's impossible to have half a pixel and different browsers will render that half a pixel differently).
I should also point out this line of code:
if (window_h > (jumbotron_h + 60)) {
var jumbotron_padding = (window_h - jumbotron_h)/2
} else {
var jumbotron_padding = 30
}
This forces your page to always be #main.height() + 60, which can be bigger than your viewable window, depending upon your window size. #main.height() comes out to around 200.5px (there we are with another half pixel).
Assuming that your goal is to vertically center the #Main element, your best bet is to use one of the many straight CSS methods available. The table method seems most applicable here because it is completely dynamic (and thus can be responsive) - simply create a single cell CSS table, use CSS valign, and build your entire page inside that cell. For older versions of IE you'll need to use a tiny hack (display:Inline-block;) to make it work.
HTML:
<div id="parent">
<div id="child">Content here</div>
</div>
CSS:
#parent {display: table;}
#child {
display: table-cell;
vertical-align: middle;
}
IE fix:
#child {
display: inline-block;
}
Based on #Thomas's answer, I've identified two possible solutions. I am going with the #2 solution considering better browser support for it.
1. Using the unit vh (viewport height). Browser support: IE9 and above.
CSS:
.home #primary { /* Parent */
display: table;
width: 100%;
}
.home #main { /* Child */
display: table-cell;
height: 100vh; /* 100% viewport height */
vertical-align: middle;
}
2. Dynamically setting height of parent (.home #primary) equal to that of browser's viewport.
JS:
jQuery(document).ready(function($){
var window_h = $(window).height();
var jumbotron_h = $('.home #main').height();
if (window_h <= (jumbotron_h + 60)) {
var window_h = jumbotron_h + 60
}
$('.home #primary').attr('style', 'height:'+window_h+'px;');
});
CSS:
.home #primary { /* Parent */
display: table;
width: 100%;
}
.home #main { /* Child */
display: table-cell;
height: 100%; /* 100% height of parent */
vertical-align: middle;
}
body {
height:100vh;
}
.element-to-be-centered {
font-size:1em;
text-align:center;
top: 49%;
-webkit-transform: translateY(-49%);
-ms-transform: translateY(-49%);
transform: translateY(-49%);
}
I have been doing quite a bit of experimenting lately with centering content. This technique will work without having to set a height on any element.
This will work in ie9 and up.
In your CSS
html, body {
height: 100%;
}
div, #main {
height: 100%;
}
I have implemented this fixed grid: http://jsfiddle.net/challenger/UxzCa/1. There are two requirements:
images should fit into a square card div (width/height can be different);
card dimensions shouldn't be fixed.
As for dimensions it is possible to implement using jquery and recalculate widths/heights on window.resize event. Are there alternative ways?
I have a partial solution that takes care of the image aspect-ratio issue and the fixed-width issue.
For the fixed-width of the grid, set the width: auto and this will allow the floats
to wrap to as many lines as required:
.grid-row {
width: auto;
margin: 0 auto;
}
The images need to scale with height if they are portrait (height/width > 1) or width if they are landscape (height/width < 1).
Define the following classes:
.table-cell img.portrait {
height: 100%;
}
.table-cell img.landscape {
width: 100%;
}
and then use the following jQuery method to set the correct class based on the aspect ration of each image:
$('.table-cell').each(function(){
var image = $(this).find('img');
aspectRatio = image.height()/image.width();
if (aspectRatio > 1)
{
image.addClass('portrait');
}
else
{
image.addClass('landscape');
}
});
See Demo Fiddle
Footnote
It may be possible to make the .card elements responsive and maintain their aspect ratio using some CSS techniques similar to the ones presented in the following question:
How do you vertically center absolute positioned text w/o declaring container size and w/o JS?