Responsive Masonry layout without predefined widths - javascript

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',
});
});

Related

Jquery-ui resizable function not working proparly with a flexbox div

I am trying to create two divs where one of which is resizable and the other takes the remaining available space in the parent container which holds the two divs.
Using flexbox model, i placed both divs beside each other and gave the one on the left a with of 50% and the one on the right flex: 1 so it takes the available space.
I then used jquery-ui resizable function on the div by the left. But when i resize the div by the left, it only decreases on mouse drag and does not increase, neither does the div to the right decrease..
I am trying to archive something like that of codepen, with multiple resizable divs layed out vertically or horizontally
Here is my code
HTML
<div class="wrapper">
<div class="left-div" id="resizable"></div>
<div class="right-div">
</div>
CSS
.wrapper{
width: 100%; // 100% of the body
height: 100vh; // take the entire view-port height
display: flex;
}
.left-div{
position: relative
width: 50%; // 100% of the parent div(wrapper)
height: 100%;
}
.right-div{
position: relative
flex: 1;
}
JS
$(document).ready(function () {
$("resizable").resizable({
handles: "e",
autoHide: true,
maxWidth: ""
});
})
$(document).ready(function () {
$("#resizable").resizable({
resize: function(event, ui) {
ui.size.height = ui.originalSize.height;
}
});
})
Check out this CodePen
I added a function to lock the resizable along Y axis.
Also, remember to add # before id selector.

How to get the height and width of window in bootstrap

In bootstrap I have a fixed top nav bar and fixed bottom nav bar. I want to show a large image in the background between the space of those two nav bars and I also want to cover the width of the window. How can I dynamically get the height between the navbars and the width of the window? The window size may change depending on device.So I need it dynamic
Requires jquery:
var viewport = {
width : $(window).width(),
height : $(window).height()
};
//can access dimensions like this:
//viewport.height
Though you won't always get perfect results, different devices behave differently and this gives the viewport dimensions, not the screen dimensions.
Alternatively you could check the width of a data-role="page" element to find the device-width (since it's set to 100% of the device-width):
var deviceWidth = 0;
$(window).bind('resize', function () {
deviceWidth = $('[data-role="page"]').first().width();
}).trigger('resize');​​​
$(window).resize(function() {
var top_nav_height = $("#id_of_top_nav").height();
var bottom_nav_height = $("#id_of_bottom_nav").height();
var window_height = $(window).height();
var height_of_open_space = window_height - (top_nav_height+bottom_nav_height);
$("#id_of_img").css({
height:height_of_open_space+'px';
});
});
this will be fine with if 0px padding and margin, if not also get that values and subtract from height_of_open_space before applying to img height
It is a bit hard to tell without seeing any of your markup, but it should be feasable with pure css. I set up a very basic example to demonstrate:
http://codepen.io/anon/pen/XbGJJO
HTML:
<div class='top'>
top navbar
</div>
<div class='content'>
<p> some content </p>
</div>
<div class='bottom'>
bottom navbar
</div>
CSS:
.top, .bottom {
height: 40px;
background: red;
position: fixed;
width: 100%;
}
.top {
top: 0;
}
.bottom {
bottom: 0;
}
.content {
margin: 40px 0;
min-height: calc(100vh - 80px);
background: green; /* background goes here */
}
The trick lies in the following line:
min-height: calc(100vh - 80px);
This tells your content to at least take up 100% of the vertical height, minus the height of the top and bottom bar. Let me know if you want me to explain further.

What's the cleanest way to make a resizable three-column layout?

Sorry if the title isn't descriptive, but I'm working on a web-based application in javascript using the HTML5 canvas. I want the page to adjust to the window size, but I also want the columns to be resizable - that is, you can drag the vertical lines to change their width. The thing is, the canvas width and height attributes must be in pixels (setting the CSS properties stretches the image instead of widening the drawing surface). I need to change the canvas attributes through javascript. I have trouble working with all of these constraints together.
I tried Making the templates-panel float left and the properties-panel float right, but it ends up below the canvas and above the status-bar everytime. I've also got the status bar set to position:fixed but it tends to go above the canvas a bit. How would you do it? Keep in mind I have to be able to resize the window or the panels individually (except the menubar and status bar which never change size).
EDIT: quick edit to add that I can't use JQuery / JQuery-UI. The application is quite computer-intensive, so I had to get rid of it. My compatibility target is IE9 anyway.
I did a quick google search on how to do this and found a stack overflow post with a similar answer, here is the fiddle that was provided, here is the javascript portion:
var i = 0;
$('#dragbar').mousedown(function(e){
e.preventDefault();
$('#mousestatus').html("mousedown" + i++);
$(document).mousemove(function(e){
$('#position').html(e.pageX +', '+ e.pageY);
$('#sidebar').css("width",e.pageX+2);
$('#main').css("left",e.pageX+2);
})
console.log("leaving mouseDown");
});
$(document).mouseup(function(e){
$('#clickevent').html('in another mouseUp event' + i++);
$(document).unbind('mousemove');
});
http://jsfiddle.net/gaby/Bek9L/
And here is the post:
Emulating frame-resize behavior with divs using jQuery without using jQuery UI?
The fiddle uses jQuery but not jQuery UI,
You will need to use percentages for width, look into responsive design.
http://learn.shayhowe.com/advanced-html-css/responsive-web-design/
I hope this helps
it's this are you looking for?
fiddle link
<style>
/* COLUMN SETUP */
.col {
display: block;
float:left;
margin: 1% 0 1% 1.6%;
}
.col:first-child { margin-left: 0; }
/* GROUPING */
.group:before,
.group:after {
content:"";
display:table;
}
.group:after {
clear:both;
}
.group {
zoom:1; /* For IE 6/7 */
}
/* GRID OF THREE */
.span_3_of_3 {
width: 100%;
}
.span_2_of_3 {
width: 66.1%;
}
.span_1_of_3 {
width: 32.2%;
}
/* GO FULL WIDTH AT LESS THAN 480 PIXELS */
#media only screen and (max-width: 480px) {
.col { margin: 1% 0 1% 0%;}
.span_3_of_3, .span_2_of_3, .span_1_of_3 { width: 100%; }
}
</style>
<div class="section group">
<div class="col span_1_of_3" style="background-color:red;color:white;text-align:center;">
template
</div>
<div class="col span_1_of_3" style="background-color:blue;color:white;text-align:center;">
canvas
</div>
<div class="col span_1_of_3" style="background-color:gray;color:white;text-align:center;">
properties
</div>
</div>

Auto height grid

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 {
}

How to center images while keeping them responsive?

Hi please take a look at my site, below is the code snippet in question i have to center my images since ive never had any luck with the css-html methods. The problem is because its set to wait for document.ready() sometimes it will place all my images to the right. Ive tried window.load() but the images center offscreen at smaller window sizes. It was also suggested i try
<div style="
background: url('Assets/image.png') center center no-repeat;
width: 100%;
height: 500px;
">
</div>
but this causes it to lose responsiveness. Ive searched around and i cant find a solution, i just need my images (and the one form) to stay centered and for the images to scale down with the window size.
site: http://bit.ly/11nAQJK
<script type="text/javascript"> //Centering Script
$(document).ready(function () {
updateContainer();
$(window).resize(function() {
updateContainer();
});
});
function updateContainer() {
(function ($) {
$.fn.vAlign = function() {
return this.each(function(i){
var h = $(this).height();
var oh = $(this).outerHeight();
var mt = (h + (oh - h)) / 2;
$(this).css("margin-top", "-" + mt + "px");
$(this).css("top", "50%");
$(this).css("position", "absolute");
});
};
})(jQuery);
(function ($) {
$.fn.hAlign = function() {
return this.each(function(i){
var w = $(this).width();
var ow = $(this).outerWidth();
var ml = (w + (ow - w)) / 2;
$(this).css("margin-left", "-" + ml + "px");
$(this).css("left", "50%");
$(this).css("position", "absolute");
});
};
})(jQuery);
Remove that whole script. Place this in your CSS.
img{
display: block;
margin: 0 auto;
}
just do
<style>
a{
display:block;
text-align:center;
}
</style>
<a href="Assets/OrderSheet.xls">
<img src="Assets/OrderSheet.png" class="image">
</a>
no need for repositioning
fiddle
No need for js, CSS alone is fine. Set your image to display block, set a width and Max width plus margin auto.
img {
display: block;
width: 300px;
max-width: 100%;
margin: 0 auto;
}
If you won't accept the method suggested by others, I would suggest using em's. Best to use them everywhere, but you could just apply them to your images.
Then use media queries to scale up/down all elements with values specified in em's, by changing the base font-size for different screen sizes.
center a responsive sized element
/* element/id/class */
/* margin is 100 - width / 2 */
img {
width:34%;
margin: 0 33%;
}

Categories