Remaking fixed grid to a responsive grid - javascript

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?

Related

Scale HTML image width and height in %

I know that width and height property of HTML images can be set simply by <img src="Debian.jpg" style="height: 120px; width: 130px">.
What I am looking for is if there exists a single CSS property that takes only one value in % and scales the width and height of the original image according to that percentage. For example, if the height and width of Debian.jpg are 1000x700 and I specify 50% in that CSS property then the image scales down to 500x350 and hence the aspect ratio is maintained.
It's very hard for me to maintain the aspect ratio of the image while adjusting the height and width separately. If a property like that does not exist then is there any way to maintain the aspect ratio and achieve desirable dimensions of the image?
Yes, there is a way to maintain the image's aspect ratio and resize the image to a fraction of its original size. However, CSS cannot know the intrinsic size (the original size) of the image. Therefore, you can only do two things:
Tell the CSS explicitly the original size
Use JS to get the original size upon image load
What doesn't work
Using percentage value as the width value for img doesn't work simply because percentage value resolves to, well, a percentage of its container size, not its original size. Below, I demonstrated the not-working examples.
That being said, I personally usually want to specify the width of the image explicitly. For example, on large devices, I want the image to be 1080px. On smaller devices, I want the image to be 560px. I can simply make a container for the image of an explicit size, place the image inside the container, and specify the image's width to 100% (of its container size).
What works
As mentioned, there are two ways to make an image 50% of its original width. First, using JS. Second, tell the CSS explicitly the original image width.
Using the JS approach, you simply need to change the width of the image. Upon load, get the intrinsic width of the image, then set the new width to the intrinsic width divided by 2. Simple.
Using the telling-CSS-explicitly approach is less advantageous. This solution presumes that the image will always be the same and needs you, the developer, to know the original image size beforehand. When you change the original image size, you will also need to update your code. That being said, you can achieve this by specifying a CSS custom property inside the CSS class, specifying an attribute (in HTML) that gives the intrinsic width then using attr() (still experimental and mostly not supported), or using an intrinsicsize attribute and set the width and style through CSS (still experimental and not supported). The last two solutions, as mentioned, are not supported by most browsers and may not work properly yet.
In my opinion, your best bet to set an image's width to 50% its intrinsic width is by using JS. Here's a solution demonstrating the what-doesn't-work solutions and the JS solution. Aspect ratio is automatically maintained if you only change one of the image's size (width/height).
const imageJS = document.querySelector('.image--changed-with-js')
imageJS.onload = () => {
const intrinsicWidth = imageJS.width
imageJS.width = imageJS.width / 2
}
* {
box-sizing: border-box;
}
body,
html {
margin: 0px;
}
img {
margin: 20px 0;
}
/* Image has its intrinsic size (i.e. the original image size) */
.image--original {
width: auto;
}
/* Image contained within a 500px container
Image has a width of 50% of 500px = 250px */
.container {
width: 500px;
}
.image--changed-with-container {
width: 50%;
}
/* Image is not contained within a div
However, image is inside body
<body> is its container
It now has a width of 50% of the body
NOT 50% of its intrinsic width */
.image--changed-without-container {
width: 50%;
}
/* Image changed using JS
You can get the intrinsic size through JS and modify its size there */
.image--changed-with-js {}
<img class="image--original" src="https://img.freepik.com/free-vector/abstract-galaxy-background_1199-247.jpg?size=626&ext=jpg">
<div class="container">
<img class="image--changed-with-container" src="https://img.freepik.com/free-vector/abstract-galaxy-background_1199-247.jpg?size=626&ext=jpg">
</div>
<img class="image--changed-without-container" src="https://img.freepik.com/free-vector/abstract-galaxy-background_1199-247.jpg?size=626&ext=jpg">
<img class="image--changed-with-js" src="https://img.freepik.com/free-vector/abstract-galaxy-background_1199-247.jpg?size=626&ext=jpg">
If you set the width to a fixed number of pixels, e.g. img { width: 500px; }, the height will adjust accordingly to maintain the same aspect ratio. If you set the height, the width will adjust accordingly to maintain the same aspect ratio.
If you set the width to a percentage, e.g. img { width: 50% }, the browser will assume you mean a percentage of the element's container. The height will adjust accordingly to maintain the same aspect ratio.
However, if you set the height to a percentage, e.g. img { height: 50% }, that just won't work for various reasons.
The solution is really simple. To preserve the aspect ratio, all you need to do is set the height and width CSS properties like:
#theImage {
width: 100%;
height: auto;
}
<img id="theImage" src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg">
By setting the width property to 100%, you are telling the image to take up all the horizontal space that is available. With the height property set to auto, your image's height changes proportionally with the width to ensure the aspect ratio is maintained. The end result is an image that scales up or down perfectly.
The downside of this solution is that a single image cannot effectively display across the range of resolutions on which your content may be viewed. For a more comprehensive solution, you need to bring in media queries and images of varying sizes to replace a lower resolution image when the time is right
My suugestion is to remove the specified sizes you put. Yes there is a code that can be specified in css.
in html do like that:
<img src="Debian.jpg" alt="Debian Image" class="myCustomImages">
in css do something like that:
.myCustomImages {
max-width: 50%;
max-height: 50%;
}
So as I understand, You want to keep the image aspect-ratio while defining it's scale in percentage of the original size. Below is my suggestion:
When the image is inside a container with display: inline-block, you can define a width for an image in css, and it will be relative to itself (if the parent have display: block it will be relative to it's parent, if it's display:inline it will be relative to the nearest block parent).
When you define one of the dimentions (width or height) and not the other, by default it's keep the aspect ratio.
So what I suggest to do is wrap the image in an inline-block parent, and define only width in a percentage. like this:
div {
display: inline-block;
}
#half {
width: 50%;
}
#original {
width: 100%;
}
#big {
width: 150%;
}
<h1>Image 400X267</h1>
<h3>50% size</h3>
<div>
<img id="half" src="https://bloximages.newyork1.vip.townnews.com/unionleader.com/content/tncms/assets/v3/editorial/f/f4/ff44150d-01ca-5e2d-8f7d-9d17e9faadd4/5dfa95339e09c.image.jpg?resize=400%2C267"/>
</div>
<h3>100% size</h3>
<div>
<img id="original" src="https://bloximages.newyork1.vip.townnews.com/unionleader.com/content/tncms/assets/v3/editorial/f/f4/ff44150d-01ca-5e2d-8f7d-9d17e9faadd4/5dfa95339e09c.image.jpg?resize=400%2C267"/>
</div>
<h3>150% size</h3>
<div>
<img id="big" src="https://bloximages.newyork1.vip.townnews.com/unionleader.com/content/tncms/assets/v3/editorial/f/f4/ff44150d-01ca-5e2d-8f7d-9d17e9faadd4/5dfa95339e09c.image.jpg?resize=400%2C267"/>
</div>

how to make a div a percentage of the overall body height?

I'm trying a more fluid design.
I want specific divs to be a percentage of the overall body. I also want to set fluid / liquid padding within each div.
<body>
<div class='image'></div>
<div class='fourty'></div>
<div class='sixty'></div>
</body>
CSS:
body {
margin-top: 85px;
min-height: 100%;
}
.image {
content: image_url('something.jpg');
width: 100%;
height: auto;
}
/*I'm assuming the padding I'm setting is a percentage of the .fourty
div not the overall body. Granted, width is 100%.*/
.fourty{
padding: 4% 8%;
min-height: 40%;
width: 100%;
}
.sixty{
padding: 4% 8%;
min-height: 60%;
width: 100%;
}
The problem I'm having is that the percentage height does not seem to take effect for these divs. It seems to just be an auto height based off the contents of the div.
How do I correct / achieve this? I'm open to a JS solution, but would be more interested as to how to accomplish this in CSS.
As far as CSS goes, there are no styles that you can apply to make an element's height equal to a certain percentage of the total document (body) height.
CSS does, however, offer you options to style an element's heights to a certain percentage of the viewport height (using VH units), but since this does not achieve your goal, I'll leave you with a javascript answer that does.
Relevant javascript functions:
function getDocumentHeight() {
return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight);
};
function setDivHeight(target, percentage) {
var desiredHeight = getDocumentHeight() * (percentage/100)
target.style.height = desiredHeight + 'px';
};
To set the height initially and on viewport resizes:
var targetDiv = document.getElementById('target');
setDivHeight(targetDiv);
window.addEventListener('resize', setDivHeight.bind(null, targetDiv))
The problem I'm having is that the percentage height does not seem to take effect for these divs. It seems to just be an auto height based off the contents of the div.
That is correct. The reason is that your code is in violation of the spec.
From the W3C height property definition:
percentage Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's
containing block. If the height of the containing block is not
specified explicitly and this element is not absolutely positioned, the value computes to 'auto'.
auto The height depends on the values of other properties.
In other words, if you're going to use percentage values, you'll need to use the height property from top to bottom.
From the browser's perspective, min-height (and max-height) don't adhere to this rule and, therefore, as the spec says, they compute to auto.
DEMO (with your code, revised)
Read more here: Working with the CSS height property and percentage values
As an aside, I think its safe to say that the height definition is thoroughly obsolete. It hasn't been updated since 1998 (CSS2) and there are many ways for establishing the height of a box. Confining percentage heights to only the height property doesn't make much sense anymore.
Firefox seems to agree. Recent versions now accept flex heights, as well. See examples here:
Height is not correct in flexbox items in Chrome
Chrome / Safari not filling 100% height of flex parent
Flexbox in Chrome--How to limit size of nested elements?

Auto re-size container if inner elements too small

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

How can I allow resizable() to increase size beyond initial size?

Is there a way to decouple css's max-height and max-width from the limits used by JQuery-UI's resizable()?
I have a div that, when initially created, should be limited in size:
.my-div {
max-width: 40em;
max-height: 50%;
}
I want it to be resizable beyond its initial size, but unfortunately resizable() seems to use these attributes to also determine the maximum size for resizing. Trying to override that by passing maxHeight and maxWidth options doesn't work. Is there a way to solve this, or some other-work around that will allow me to limit the initial size of the div and later on allow it to increase via resizable()?
I've found an identical question on jquery.com, but it's unanswered there.
A small reproducing jsfiddle - how can I allow resizing the div to see the ".com" suffix, while keeping only the "stackoverflow" word visible at first?
Did you try resetting CSS values via jQuery (not tested) ?
$(".my-div").css({
"max-width": "60em",
"max-height": "75%"
});
Update :
From you fiddle, I tried this :
.my-div {
width: 90px;
max-width: 130px;
overflow: hidden;
background-color: yellow;
}
Could it solve your problem ?
I ended up just implementing the "maximum" logic on the div manually to limit its size, instead of relying on max-width:
if ($div.width() > limit) $div.css('width', limit);
http://jsfiddle.net/yzn5pnhn/2/

Making an element fill the entire height of browser viewport using jQuery

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%;
}

Categories

Resources