Auto height grid - javascript

I have a product grid on my e-shop (http://shop.rukahore.sk/). Every product div is 222px x 222px, but I want it to have auto height.
I tried something like this - http://patterntap.com/code/stacking-columns-layout-masonry ,
but I had to add min-height and it didn't look good because some of the images were smaller or bigger and wrapping div was still 222px, which I don't want to happen due to hover effect, etc.
Can someone provide advice regarding this?

Well, for using the display shown in that page you need to use the plugin
<!-- Requires Masonry | visit http://masonry.desandro.com/ to download -->
If you don't want to add more plugins... Well, what makes you lose the height is the float css property. You should use other thing to make the grid, see for example how they do it in www.camarasdecolores.com.
To add the Masonry plugin:
Add an id to your container:
<div id="masonryContainer" class="hp-products allposts" style="position: relative; height: 2008px;">
Add the init js code in a script
$(window).load(function(){
$('#masonryContainer').masonry({
itemSelector: '.hp-product',
columnWidth: 60
});
});
change some css:
#masonryContainer { width: 0 auto; }
.hp-product {
width: 180px; float: left;
}
.hp-product-img {
}
.hp-product-img img {
max-width: 100%;
height: auto;
}
//Void the following ones
.hp-products {
}
.allposts {
}
.allposts .hp-product {
}

Related

Preventing IMG from Resizing and Inconsistent Div Height Change?

Currently I have a huge div that would collapse from the height it automatically generated to the height of the title of the div. (i.e. 32px). I have it start out collapsed and then when I click on the div it opens to its full size, displaying all its inner information, and then when I click again, it collapses again. Unfortunately, two things happen:
The div doesn't completely expand to its full height.
The first large img in the div gets resized.
Now I understand why the latter is happening. It has something to do with the height being a percentage instead of a discrete number, for when I change the number to something like 500px, it works just fine. But I don't want to do that. I need it to remain a percentage for when I need to use, yet resize, large pictures.
I also feel this same problem may coincide with the former problem as well, but I'm not sure.
Please help me with this.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>This is the title</title>
</head>
<body>
<div class="example"> <span class="h2">DIV Example</span>
<br />
<img class="big" src="http://www.greenbookblog.org/wp-content/uploads/2012/03/big-data.jpg" />
<p>This is a big picture. It's here to show what this thing is supposed to be doing.
However, this picture has been squished so that it can fit within the div nicely. I am
writing a bit so that I can take up space.</p>
<img class="big" src="http://www.greenbookblog.org/wp-content/uploads/2012/03/big-data.jpg" />
<p>This is a big picture. It's here to show what this thing is supposed to be doing. However, this picture has been squished so that it can fit within the div nicely. I am writing a bit so that I can take up space.</p>
</div>
</body>
</html>
CSS:
div.example, div.example img {
border: 3px solid #402468;
border-radius: 6px;
}
div.example {
color: white;
margin: 0 15px;
background-color: #504689;
overflow: hidden;
}
img {
display: block;
margin: 0 auto;
}
img.big {
width: 85%;
height: 85%;
}
/*further formatting: pay no mind*/
div p {
text-indent: 15pt;
margin: 0 15px;
}
.h2 {
font: 32px"Times New Roman", serif;
color: #678900;
}
aaaand jQuery:
$(document).one("ready", function () {
$("div.example").each(function () {
$(this).data("height0", $(this).height());
$(this).height("32px");
});
});
$(document).ready(function () {
$("div.example").click(function () {
if ($(this).height() !== 32) {
$(this).animate({
height: '32px'
});
} else {
$(this).animate({
height: $(this).data("height0")
});
}
});
});
Here is the fiddle:
https://jsfiddle.net/AirStyle/rb95K/35/
Also this is what I get:
https://jsfiddle.net/AirStyle/rb95K/35/embedded/result/
CAUTION: I may not have made the percentages small enough for the picture used. Please lessen them if necessary.
Just remove the height setting altogether and it will keep aspect ratio
(Demo)
img.big {
width: 85%;
}
Also you should cache your jQuery objects. I've done this in the demo by caching $(this) to var self = $(this) and then referring to self therein. There is a lot of overhead in initializing jQuery objects, so if you're using the same selector more than once, cache it.
Edit:
Because you are setting the height of the div to a fixed height on expansion, if the user resizes the window the images will grow in width as well as height. As the container is a fixed height the contents will grow past the end of the container and get cut off. If you would like to fix that, add a "complete" function to the animation to remove the height setting and make it dynamic again.
(Demo)
self.animate({
height: self.data("height0")
},function() {
self.height('');
});
You can also add height: auto; to maintain the default aspect ratio.
img.big {
width: 85%;
height: auto;
}

Responsive Masonry layout without predefined widths

I'm creating a 2 column masonry layout using images of different sizes. The images can be any size as long as they have the greatest common divisor (as required by the Masonry plugin).
In order to make the layout responsive I'm converting the width of the masonry items into percent (or I can use min-width and width 100%).
Update: I noticed that many who answer make both columns 50% as a solution. That works but is not the goal. Images have to retain their original image size. They can shrink but keep the same ratio.
$(function () {
var container = $('#container');
// Convert .box width from pixels to percent
$('.box').find('img').each(function () {
var percent = ($(this).width()) / container.width() * 100 //convert to percent;
$(this).closest('.box').css('max-width', percent + '%');
});
// Trigger masonry
container.masonry({
itemSelector: '.box',
columnWidth: 1 //widths dividable by 1
});
});
jsfiffle: http://jsfiddle.net/AMLqg/278/
This seems to work. The items are fluid when you resize the window. However if you load the script in a small window size (smaller than the 2 column width) the items collapse. How can I keep the masonry items responsive on window load even when the window is smaller?
Update: Here is more info for a better understanding. I'm trying to keep 2 responsive columns regardless of the window size. The columns can't have equal widths because the images have different widths. For this reason I'm using columnWidth: 1 because all widths are dividable by 1.
Please see images below for examples.
Problem: When you open the page in a small window the elements are collapsed. When you resize the window to be larger the elements remain collapsed until the window width is larger than the width of both elements.
Goal: I'm trying to keep the elements in 2 responsive columns on load like in the image below. Currently they remain responsive if on load the window is large and you resize it to be smaller but not vice verse when window is small on load and you make it larger.
You can try overflow:hidden on the surrounding box.
Using imagesloaded.js and columnwidth set using css like so:
jsFiddle
<div id="container">
<div class="grid-sizer"></div>
<div class="box">
<img src="http://images.huffingtonpost.com/2007-11-01-ice.jpg" />
</div>
<div class="box">
<img src="http://www.wwalls.ru/mini/201211/57608.jpg" />
</div>
<div class="box">
<img src="http://artistsandwriters.com/site/wp-content/uploads/2014/09/IMG_7303LR-390x150-1412284267.jpg" />
</div>
</div>
Script
$(document).ready(function () {
var container = $('#container');
$('.box').find('img').each(function () {
var percent = $(this).width() / container.width() * 50;
$(this).closest('.box').css('max-width', percent + '%');
});
// Trigger masonry
container.imagesLoaded(function () {
container.masonry({
itemSelector: '.box',
columnWidth: '.grid-sizer'
});
});
});
CSS
#container {
max-width:580px;
}
.box {
float: left;
margin-bottom: 5px;
}
.box img {
width: 100%;
}
.grid-sizer {
width: 50%;
}
Are you looking for something like this?
Fiddle
So, all we're doing here is getting rid of your percentage calculation (of which I really don't understand the necessity), and setting a min-width on the .box class. Just like this:
.box {
float: left;
min-width: 100px;
}
I was able to reproduce your problem. This is how it looks for those curious:
The problem is your float: left rule in the CSS, which is collapsing the box when Masonry is doing its positioning calculations after adding the image. You can do a simple clear-fix to keep this if you really need to keep that clunky percentage calculation, like so:
.container:after {
content: '';
display: table;
clear: both;
}
Hope that helps!
Edit – Based on your comments:
Okay, if you always want there to be two columns, it's an even simpler change:
Get rid of this Javascript
// Convert .box width from pixels to percent
$('.box').find('img').each(function () {
var percent = $(this).width() / container.width() * 100;
$(this).closest('.box').css('max-width', percent + '%');
});
Add this CSS
.box {
max-width: 50%;
}
Fairly straightforward, I think.
Here's a fiddle, just for giggles
EDIT
Check this http://jsfiddle.net/gk3t009j/2/
CSS
#wrapper
{
background-color: red;
margin: 0 auto; max-width:580px;
}
#container,
{
overflow: hidden;
width: 100%;
}
.box
{
max-width: 290px!important; width: 50%;
}
.box img{width: 100%;}
JS
$( window ).load( function()
{
var wc=$( '#container').width();
wc=parseInt(wc);
if( wc % 2)
{
var wb=$('.box').width();
wb--;
$('.box').width(wb)
}
$( '#container').masonry(
{
itemSelector: '.box',
columnWidth: function( containerWidth ) {
return parseInt(containerWidth / 2);
}
});
});
HTML
<div id="wrapper">
<div id="container">
<div class="box">
<img src="http://images.huffingtonpost.com/2007-11-01-ice.jpg" />
</div>
<div class="box">
<img src="http://www.wwalls.ru/mini/201211/57608.jpg" />
</div>
<div class="box">
<img src="http://artistsandwriters.com/site/wp-content/uploads/2014/09/IMG_7303LR-390x150-1412284267.jpg" />
</div>
</div>
</div>
I removed the JS code and some of the HTML markup and updated the styling:
#container {
width: 100%;
}
img {
display: inline;
vertical-align: top;
float: left;
min-width: 50%;
width: 50%;
}
http://jsfiddle.net/org6nsr8/8/
I agree with Josh Burgess on that Masonry is not needed to accomplish this, take a look and see if this is what you're after.
I'd be happy to elaborate if something is unclear or you want anything explained.
You don't need the JavaScript; just change the css for .box to:
.box {
float: left;
max-width: 50%;
}
I am not sure if this is what you need. If I understood the problem correctly may be you need to use max-width instead of width.
Here is example fiddle :
http://jsfiddle.net/AMLqg/304/
My JS code :
$(function () {
var container = $('#container');
var maxWidth = container.css("maxWidth");
maxWidth = parseInt(maxWidth.substring(0,maxWidth.indexOf("px")));
// Convert .box width from pixels to percent
$('.box').find('img').each(function () {
var percent = ($(this).width()) / maxWidth * 100;
console.log(percent);
$(this).closest('.box').css('max-width', percent + '%');
});
// Trigger masonry
container.masonry({
itemSelector: '.box',
columnWidth: 1 //widths dividable by 1
});
});
After trying several library to make a masonry layout , I prefer salvattor.js
Very easy to use. the size of the columns you can configure css.
#media screen and (max-width: 480px){
#grid[data-columns]::before {
content: '1 .column.size-1of1';
}
}
What i understand you want to keep Layout 2 Column with Images on aspect ratio on all screen sizes ,
Check
http://jsfiddle.net/tasaeed/k40cgfye/
CSS
#container {
max-width: 580px;
}
.box {
float: left;
width:50%;
}
.box img {
width: 100%;
height:auto;
}
Script
$(function () {
var container = $('#container');
// Trigger masonry
container.masonry({
itemSelector: '.box',
});
});

How to make SpriteSpin responsive?

Site i am working on is made with twitter bootstrap and is fully responsive. I have successfully made SpriteSpin to work with my site but there is a problem, i can't make it responsive as rest of my site because it adds inline css to div where the image is.
JS looks like this:
First it calls images:
$(function(){
var frames = [
"folder/image.jpg",
(other images)
];
Then this:
$("#mali").spritespin({
width : 960,
height : 540,
(other code)
});
How can i change this fixed width and height and put there css class or w/h to 100% so that is responsive.
I already tried to add css class to container with this but no success:
$( "div" ).addClass( "myClass" );
I believe the problem here is that the script somehow adds inline css
<div class="spritespin spritespin-instance" unselectable="on" style="overflow: hidden; position: relative; width: 480px; height: 327px;">
You can see it on official SpriteSpin website (link below) when using inspect element on Bicycle image.
Help me fix this issue or suggest me other 360 image sprite spin solution that is responsive and works on mobile touch.
SpriteSpin: http://spritespin.ginie.eu/
You can override CSS by adding !important after your own CSS directives.
In it's simplest form:
background: red !important;
If you have inline style attributes in HTML:
<div style="background: red;">
The inline styles for this div should make it red.
</div>
you can try this CSS:
div[style] {
background: yellow !important;
}
But it's not really good practice to rely on it in production code. More info:
http://css-tricks.com/when-using-important-is-the-right-choice/,
http://css-tricks.com/override-inline-styles-with-css/
I know this is an old post but I ran into this same problem today. Basically all you need to do is set a media query at each screen size in your css to resize the container and the images will respond since their widths and heights are already set at 100%.
#media only screen and (min-width: 100px) and (max-width: 767px) {
.spritespin, .spritespin-instance {
width:383px !important;
height:300px !important;
}
}
It's great to use it with bootstrap solution for responsive embed objects
var $container = $(".images3d-container")
if ($container.length && $.fn.spritespin != undefined) {
var source = []
$container.find(".images").find('img').each(function () {
source.push($(this).attr('src'))
})
$container.find(".view").spritespin({
source: source,
animate: false,
renderer: "image",
width : 450, // width in pixels of the window/frame
height : 450 // height in pixels of the window/frame,
})
}
.images3d-container .images {
display: none;
}
.images3d-container .view {
width: 100%!important; /* here it is */
height: 0 !important;
padding-bottom: 100%;
position: relative;
overflow: hidden;
border-bottom: 1px solid #ccc;
margin-bottom: 20px;
}
<section class="images3d-container">
<div class="view"></div>
<ol class="images">
<li><img src="/img/1.jpg"></li>
<li><img src="/img/2.jpg"></li>
<li><img src="/img/3.jpg"></li>
<li><img src="/img/4.jpg"></li>
</ol>
</section>
I know this question is old, but for people that happen to look for an answer: the plugin now has a setting for this. Just add responsive: true, and set the width of the SpriteSpin. See the official demo.

How to resize a div to clients viewport height?

Ok, so i want to have a series of divs which are the exact width and height of the user's browser window, regardless of the screen size. I can easily make the divs stretch horizontally with "width: 100%;" but i cant work out how to make the height stretch itself. I am guessing that i need to use some bit of javascript to judge the height, and then another piece to resize the seperate divs. Unfortunately I am a complete javascript n00b and after two hours of seemingly fruitless searching and coming up with about 100 "solutions" this was as far as id gotten (Im sure that at some point I have probably been closer to the answer):
var viewportHeight = "height:" + document.documentElement.clientHeight;
getElementById('section-1').setAttribute('style', viewportHeight);
<div class="section" id="section-1"></div>
<div class="section" id="section-2"></div>
<div class="section" id="section-3"></div>
edit:
ah i should be more clear, im attempting to have all three divs take up the entire screen, so you have to scroll down to see each one - almost like seperate slides. The idea is that each one takes up the entire screen so you cant see the next section until you scroll down, rather than having three divs which take up a third of the screen.
If you haven't already tried it, you'll want to look at parent:child inheritance of elements within the DOM by way of using CSS.
What I want to STRESS is that everyone giving you JS hacks to accomplish this is not only providing you with overkill (YOU did ask for a JavaScript solution, so they gave it to you!), but it's also a deviation from standards. HTML is for structure, CSS is for presentation, and JavaScript is for behavioral aspects... setting a div to the width of the viewport on load is a PRESENTATION aspect and should be done in CSS... not JavaScript. If you were trying to change the width based on events or user interaction, then yes JavaScript is your friend... but stick with just HTML and CSS for now.
The trick is that most elements have an undefined height - and height is later defined by the content that the element holds.
If you want to 'trick' an element into having a height other than what it wants to default to, you'll have to explicitly define it. Since you want to inherit your height from the viewport, you'll have to define the height at the top and bring it down...
You might be in luck and can avoid JavaScript altogether (unnecessary). Just use CSS.
Try something like:
html, body {
height: 100%;
width: 100%;
}
Now, when you try to set your div's later on, specify width: 100% and the height gets inherited from the html --> body --> div.
Try that and see if that solves your problem - if not, point us to a website, a pastebin, or a SOMETHING with code in it that we can just show you how to do it (whereas what you posted for code was an attempt in JavaScript which is only 1 part of the code - post the full thing either to a server or temp site like pastebin).
Here is some sample code I wrote (tested in Chromium):
The HTML:
<html>
<head>
<title>Test Divs at 100%</title>
<link rel="stylesheet" type="text/css" href="divtest.css"
</head>
<body>
<div class="test1">aef</div>
<div class="test2">aef</div>
<div class="test3">aef</div>
</body>
</html>
The CSS:
html, body {
width: 100%;
height: 100%;
background-color: #793434;
padding: 0;
margin: 0;
}
div {
height: 100%;
width: 100%;
}
.test1 {
background-color: #E3C42E;
}
.test2 {
background-color: #B42626;
}
.test3 {
background-color: #19D443
}
try this
div#welcome {
height: 100vh;
background: black;
color: white;
}
div#projects {
height: 100vh;
background: yellow;
}
<div id="welcome">
your content on screen 1
</div>
<div id="projects">
your content on screen 2
</div>
it should work for you, but little support in IE
A bit of jQuery should do it:
$(document).ready(function() {
var window_height = $(window).height();
$('#section-1").height(window_height);
});
And if you want to keep 100% height on window resize:
$(document).ready(function() {
function viewport_height() {
var window_height = $(window).height();
$('#section-1").height(window_height);
}
viewport_height();
$(window).resize(function() {
viewport_height();
});
});
try this
window.onload = init;
function init()
{
var viewportHeight = "height:" + document.documentElement.clientHeight+"px;";
document.getElementById('section-1').setAttribute('style', viewportHeight);
}
Here is a script free solution, just CSS. This assumes that the divs are directly in the body element or a parent with position absolute and the parent has no padding.
#section-1 {
position: absolute;
height: 100%;
width: 100%;
background: #ff0000;
}
#section-2 {
position: absolute;
width: 100%;
top: 100%;
height: 100%;
background: #00ff00;
}
#section-3 {
position: absolute;
width: 100%;
top: 200%;
height: 100%;
background: #0000ff;
}
See fiddle: http://jsfiddle.net/QtvU5/1/

How do I include an element's margin in the hot-spot for jQuery's hover() event?

jQuery(".my_container").hover(function(){
//do code
}, function(){
//do code
});
.my_container { width: 100px; height: 100px; margin: 50px; }
The code above doesn't react to mouse over of margin (margin isn't a part of element?) - how can I change that?
You could use a 50px transparent border instead - the margin isn't really supposed to be mouseable...
Include a pseudo element, e.g.
.my_container:before {
content:'';
position:absolute;
top:-50px;
bottom:-50px;
left:-50px;
right:-50px;
}
This adds an extra 50px to the existing element's clickable area.
If you only want to add this on touch screen devices, you could do this:
.touchevents .my_container:before {
...
}
This requires something like Modernizer to insert the appropriate feature-based CSS class.
Update
As per #Jaladh's comments, you may also need to apply position:relative to the container element, since position:absolute above will be relative to the first ancestor with a position attribute:
.my_container {
position:relative;
}
Perhaps use a 2nd wrapper element with padding on the outer element and existing background and padding styles on the inner element:
<div class="my_container">
<div class="my_container_inner">
<!-- etc. -->
</div>
</div>
jQuery(".my_container").hover(function(){
//do code
}, function(){
//do code
});
.my_container { padding: 50px; }
.my_container_inner { width: 100px; height: 100px; /* etc. */ }
Building upon #Dunc's solution, you can alternatively use pseudo element to mimic your container and let actual container behave like margins. This will look like:
.my_container {
width: calc(100px + (2 * 50px));
height: calc(100px + (2* 50px));
position: relative;
}
.my_container::before {
content: '';
position: absolute;
top: 50px;
bottom: 50px;
left: 50px;
right: 50px;
}
Also make sure to move all other properties (like background color, border, etc.) you had in my_container to my_container::before because before is acting like our container here.
This is essentially helpful if your containers are grid items and you want gaps in-between them to be hoverable, because otherwise using psuedo element to add margins won't work appropriately in that case.
Change the margin to padding and it'll be hoverable.

Categories