Does anybody know of a script that will let me diplay image results in the way that Google Image Search does (image grid view) with hover to enlarge and details? Something that I can just "plug-and-play" so to speak.
Have a look at Masonry http://masonry.desandro.com/
First, you need to put all images inside a container element:
<div class="parent">
<img src="">
<img src="">
<img src="">
</div>
Then you need to make sure that the images are displayed in one line. This can be done by e.g. float: left. You should also set vertical-align to remove the small gap underneath each image:
img {
float: left;
vertical-align: top;
}
Finally you need some JavaScript to loop through all images and calculate the ideal rowHeight based on their dimensions. The only thing you need to tell this algorithm is the maximum row height that you want (rowMaxHeight)
// Since we need to get the image width and height, this code should run after the images are loaded
var elContainer = document.querySelector('.parent');
var elItems = document.querySelector('.parent img');
var rowMaxHeight = 250; // maximum row height
var rowMaxWidth = elContainer.clientWidth;
var rowWidth = 0;
var rowRatio = 0;
var rowHeight = 0;
var rowFirstItem = 0;
var rowIsLast = false;
var itemWidth = 0;
var itemHeight = 0;
// Make grid
for (var i = 0; i < elItems.length; i++) {
itemWidth = elItems[i].clientWidth;
itemHeight = elItems[i].clientHeight;
rowWidth += itemWidth;
rowIsLast = i === elItems.length - 1;
// Check if current item is last item in row
if (rowWidth + rowGutterWidth >= gridWidth || rowIsLast) {
rowRatio = Math.min(rowMaxWidth / rowWidth, 1);
rowHeight = Math.floor(rowRatio * rowMaxHeight);
// Now that we know the perfect row height, we just
// have to loop through all items in the row and set
// width and height
for (var x = rowFirstItem; x <= i; x++) {
elItems[i].style.width = Math.floor(rowRatio * itemWidth * (rowMaxHeight/itemHeight)) + 'px';
elItems[i].style.height = rowHeight + 'px';
}
// Reset row variables for next row
rowWidth = 0;
rowFirstItem = i + 1;
}
}
Note that this code is not tested and a very simplified version of what this vanilla JavaScript plugin does: https://fld-grd.js.org
Two solutions that I have found so far.
tutorial blog
jsfiddle
$(function() {
$(window).on('resize', function() {
$('.openEntry').remove();
$('.entry').hide();
var startPosX = $('.preview:first').position().left;
console.log(startPosX);
$('.entry, .preview').removeClass("first last");
$('.entry').each(function() {
if ($(this).prev('.preview').position().left == startPosX) {
$(this).prev('.preview').addClass("first");
$(this).prevAll('.entry:first').addClass("last");
}
});
$('.entry:last').addClass("last");
});
$(window).trigger('resize');
$('.trigger').click(function() {
$('.openEntry').slideUp(800);
var preview = $(this).closest('.preview');
preview.next('.entry').clone().addClass('openEntry').insertAfter(preview.nextAll('.last:first')).slideDown(800);
});
$('body').on('click', '.close', function() {
$('.openEntry').slideUp(800).remove();
});
})
codrops actually puts the photo enlargement/details inline instead of as a modal overlay:
http://tympanus.net/codrops/2013/03/19/thumbnail-grid-with-expanding-preview/
This might be what you are looking for... http://www.gethifi.com/demos/jphotogrid
Have a look at the gPop plugin
DEMO
Download in Github
Check out this jQuery Plugin: https://github.com/brunjo/rowGrid.js
It places images like on the Google image search.
Simply just repeat your images like this:
<img style="float: left; height: 12em; margin-right: 1%; margin-bottom: 0.5em;border:1px solid lightgray" src="ImgSrc " />
Related
I want to cut the margin-left of a div container in half under a certain window width (mobile).
I've tried this with parseInt, .css and store it temporarly in a variable. Then cut it in half and use .replace.
if ($(window).width() <= 590) {
let oldmargin = parseInt($("#div").css("marginLeft"));
let newmargin = oldmargin/2;
$("#div").css("marginLeft").replace('rem', newmargin);
}
Unfortunately the code is not working.
To set a new value of margin-left, try with $("#div").css("margin-left",newmargin);
To GET a value using .css() = $("#div").css("margin-left")
To SET a value using .css() = $("#div").css("margin-left",newmargin)
$('.div').each(function() {
var oldmargin = parseInt($(this).css("marginLeft"));
var newmargin = oldmargin / 2;
$(this).css("marginLeft", newmargin);
});
Demo
$('.div').each(function() {
var oldmargin = parseInt($(this).css("marginLeft"));
var newmargin = oldmargin / 2;
$(this).css("marginLeft", newmargin);
});
.div {
margin-left: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="div">#div</div>
<div class="div">#div</div>
I'm trying to get all image elements on a html page then check each image if the width < height (portrait) then rotate it.
The problem is my script doesn't work for each image but for all of them because i get the images by "img" tag, then i have no idea how to apply the rotation for individual images.
Is it possible to do this without having to modify the markup for each images (I want to avoid putting ids for every image)?
<script>
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
img = document.getElementsByTagName("img")[i];
var width = img.clientWidth;
var height = img.clientHeight;
if(width<height){
img.setAttribute('style','transform:rotate(90deg)'); //how do I apply this for each image?
}
else{
}
}
});
</script>
Your code seems to be working for images of the correct dimensions. However, you can change your code a little. For the code that you've given you don't need to do:
img = document.getElementsByTagName("img")[i];
in your for loop at each iteration, as this is an expensive function to run. Instead, you already have the result of document.getElementsByTagName("img"); stored in imgs, so you can use that instead:
img = imgs[i];
See working example below:
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
img = imgs[i];
var width = img.clientWidth;
var height = img.clientHeight;
if (width < height) {
img.setAttribute('style', 'transform:rotate(90deg)');
}
};
});
img {
height: 150px;
width: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Width > Height</p>
<img src="https://media.wired.com/photos/5926db217034dc5f91becd6b/master/w_1904,c_limit/so-logo-s.jpg" />
<p>Width < Height</p>
<img src="https://d1qb2nb5cznatu.cloudfront.net/startups/i/32728-274244db60c65e1cc32abb4c54a2c582-medium_jpg.jpg?buster=1442602512" />
<p>Width < Height</p>
<img src="https://images.unsplash.com/photo-1522092787785-60123fde65c4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94d6ebf03fdc6a3c8159ac9aeceb0483&w=1000&q=80" />
Also, since your using jQuery, this can be done even easier using jQuery methods:
$(document).ready(function() {
$('img').each((_, elem) => {
let width = $(elem).width();
let height = $(elem).height();
if(width < height) {
$(elem).css({'transform': 'rotate(90deg)'});
}
});
});
img {
height: 150px;
width: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Width > Height</p>
<img src="https://media.wired.com/photos/5926db217034dc5f91becd6b/master/w_1904,c_limit/so-logo-s.jpg" />
<p>Width < Height</p>
<img src="https://d1qb2nb5cznatu.cloudfront.net/startups/i/32728-274244db60c65e1cc32abb4c54a2c582-medium_jpg.jpg?buster=1442602512" />
<p>Width < Height</p>
<img src="https://images.unsplash.com/photo-1522092787785-60123fde65c4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94d6ebf03fdc6a3c8159ac9aeceb0483&w=1000&q=80" />
I tried the code provided and on many occasion (reload for instance) it doesn't get the width and height of the image.
It seems that instead of using
$(document).ready(fn)
you should use
$(window).on("load", fn)
There was a question on this topic Official way to ask jQuery wait for all images to load before executing something
<script>
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
var img = document.getElementsByTagName("img");//add all images in array
var width = img[i].clientWidth;
var height = img[i].clientHeight;
if(width<height){
img[i].setAttribute('style','transform:rotate(90deg)'); //change style for current image
}
else{
}
}
});
</script>
I'm trying to set, with javascript, the width of one div to the width of another. In my case, the second div was cloned from the first.
The issue I'm running into is related to padding, and how style.width is defined differently from clientWidth/offsetWidth/scrollWidth. In my example below, I have two divs defined the same except with different widths. When the button is pressed, I'm trying to set the width of the smaller one to the bigger one - but the outcome is that it gets the width of the bigger one PLUS the padding (an extra 20px).
Is there a way to change the line:
two.style.width = one.clientWidth + 'px';
to make the two divs equal in width?
function setWidth() {
var one = document.getElementById("one");
var two = document.getElementById("two");
two.style.width = one.clientWidth + 'px';
}
.outer {
background: red;
padding: 10px;
}
.inner {
background: green;
height: 10px;
}
#one {
width: 100px;
}
#two {
width:50px;
}
<div id=one class=outer><div class=inner></div></div>
<br>
<div id=two class=outer><div class=inner></div></div>
<button onclick="setWidth()">SET WIDTH</button>
You can use getComputedStyle:
function setWidth() {
var one = document.getElementById("one");
var two = document.getElementById("two");
style = window.getComputedStyle(one);
wdt = style.getPropertyValue('width');
two.style.width = wdt;
}
Here's a fiddle
You should make use of .offsetWidth. They belong to the element, not .style.
function setWidth() {
var w=document.getElementById('one').offsetWidth
document.getElementById('two').setAttribute("style","width:"+w+"px");
}
The width isn't taking into account the padding. You'll still need to subtract it. Something like this should work:
function setWidth() {
var one = document.getElementById("one");
var two = document.getElementById("two");
two.style.width = one.offsetWidth + 'px';
//update the width again, subtracting the difference between the first div and the second (which includes padding)
two.style.width = (two.offsetWidth-((two.offsetWidth - one.offsetWidth)*2)) + 'px';
}
You can see it working here: https://jsfiddle.net/igor_9000/55d1pfak/1/
For what its worth, jQuery handles this a little easier and gets the elements width including padding/borders. That may be another option for you.
Hope that helps!
You need to take one's padding into consideration.
function setWidth() {
var one = document.getElementById("one");
var two = document.getElementById("two");
var leftPadding = window.getComputedStyle(one, null).getPropertyValue('padding-left');
var width = window.getComputedStyle(one, null).getPropertyValue('width');
two.style.width = width;
two.style.padding = leftPadding;
}
Here's a JSFiddle.
My code will find the largest width for all elements using class 'js-equal-width' and it will set all of them to the same width.
$(function() {
const extraWidth = 50
var maxWidth = 0
$('.js-equal-width').each(function() {
maxWidth = maxWidth > $(this).width() ? maxWidth : $(this).width()
})
$('.js-equal-width').each(function() {
$(this).width(maxWidth + extraWidth)
})
})
You can do it by using 'js-equal-width'
<div style="width: 300px;">
<span class="js-equal-width">Midterm Examination</span>
<span class="js-equal-width">Final Examination</span>
</div>
I am working on a parallax site in which there are sequence of images (around 400 images). The background images change based on page scroll to create a smoothly moving animation. I managed to get the scrolling working, but when the user scrolls, the change of background images are not smooth (We can see the blank space for a second or so depending on the internet connection). Also, the images are not being cached, the page does a new request every time. How can I optimize this code so that the animation is smooth and it doesn't request a new image every time and uses the cached images. Is it efficient to create the animation in canvas? I tried canvas, but it also makes a new request to images on every scroll. Here is my code using standard background changing based on page scroll:
HTML
<div class="container">
<div id="background-images" class="background-images">
<div class="test"></div>
</div>
</div>
CSS
#background-images{
height: 4000px;
}
.container{
border: 1px solid red;
height: 400px;
overflow: auto;
}
.test{
position: fixed;
top: 0;
left: 0;
z-index: 999;
width: 600px;
height: 600px;
}
Javascript
var $container = $(".container");
var $bgImage = $(".test");
// Attaching the scroll to the background image
$container.scroll(function(event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
for (var i = 0; i < totalImages; i++) {
$('<img/>')[0].src = getImgUrl(i);
}
}
preload(36); // Preload 36 images, the cache should keep these so we wont't need to load these while we scroll
// Set the background image
function setBgImage(position){
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + ", Position: " + position);
$bgImage.css("background-image", "url('" + getImgUrl(imageNum) + "')");
}
// Set a placeholder background image
function getImgUrl(num){
return "http://placehold.it/200x200/&text=" + num;
}
JSFiddle: http://jsfiddle.net/4j9u8qtf/1/
You could add all the images hidden and just show the correct one in an actual image element, instead of using css background image. I edited your jsfiddle to demonstrate:
function create(totalImages) {
for (var i = 0; i < totalImages; i++) {
var img = $('<img/>')
img[0].src = getImgUrl(i);
$bgImage.append(img)
}
setBgImage(0)
}
create(37);
function setBgImage(position){
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + ", Position: " + position);
$bgImage.find("img").hide().eq(imageNum).show()
}
http://jsfiddle.net/y92g7vvL/1/
The best way to preload images is to use the Image constructor like the example below. Using the Image constructor makes it so you don't have to worry about attaching the images anywhere to the document to make them load.
function preload(url) {
var image = new Image();
image.src = url;
}
I updated your Fiddle to use this preload and to not use jQuery for setting the background-image. It works quite well now. All images are preloaded/loaded only once.
$(function () {
var $container = $(".container");
var $bgImage = $(".test");
var bgImage = $bgImage.get(0);
$container.scroll(function (event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
function fetch(url) {
var image = new Image();
image.src = url;
}
for (var i = 0; i < totalImages; i++) {
fetch(getImgUrl(i));
}
}
preload(36);
function setBgImage(position) {
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
var url = getImgUrl(imageNum);
bgImage.style.backgroundImage = "url('"+ url +"')";
}
function getImgUrl(num) {
return "http://placehold.it/200x200/&text=" + num;
}
})
Try
html
<div class="container">
<div id="background-images" class="background-images">
<div class="test"></div>
</div>
</div>
<!-- hidden container for `img` elements -->
<div id="imgs"></div>
css
#imgs {
display:none;
}
js
$(function () {
var $container = $(".container");
var $bgImage = $(".test");
$container.scroll(function (event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
for (var i = 0; i < totalImages; i++) {
$('<img/>', {
"src": getImgUrl(i)
})
// append `img` elements to `#imgs` container
// to `cache` the images ,
// images not requested again at
// `$bgImage` `background-image` adjustments
.appendTo("#imgs");
}
}
preload(36);
function setBgImage(position) {
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + "
, Position: " + position
, $("#imgs img[src$=" + imageNum + "]"));
// utilize images already in DOM ,
// load `#imgs img` `src` as `$bgImage` `background-image` ,
// from hidden `#imgs` `div`
// images _not_ requested again from server ,
// see `network` tab at console
$bgImage.css("background-image"
, "url('" + $("#imgs img[src$=" + imageNum + "]").attr("src") + "')");
}
function getImgUrl(num) {
return "http://placehold.it/200x200/&text=" + num;
}
});
jsfiddle http://jsfiddle.net/guest271314/bh91g0tv/
The reason that they're being requested over and over is that you're using jQuery background assignment, which reloads the image.
This is silly. You don't need or want jQuery here, and it has side effects you don't understand that are causing your problem.
Just set the X position of the background. Done.
function offset_to(id, posX, posY) {
document.getElementById(id).style.backgroundPosition = posX.toString() + 'px ' + posY.toString() + 'px';
}
To create a smooth effect to your image transition just add css transition in your case:-
.test{
-webkit-transition: all 0.5s ease;
-moz-transition: position 10s;
-ms-transition: position 10s;
-o-transition: position 10s;
transition: all 0.8s ease;
}
I'm trying to do what the title says. I've seen that font-size can be a percentage. So my guess was that font-size: 100%; would do it, but no.
Here is an example: http://jsfiddle.net/xVB3t/
Can I get some help please?
(If is necesary to do it programatically with js there is no problem)
This question might help you out but I warn you though this solves it through jQuery:
Auto-size dynamic text to fill fixed size container
Good luck.
The OP of that question made a plugin, here is the link to it (& download)
BTW I'm suggesting jQuery because as Gaby pointed out this can't be done though CSS only and you said you were willing to use js...
Can't be done with CSS.
100% is in relation to the computed font-size of the parent element.
reference: http://www.w3.org/TR/CSS2/fonts.html#font-size-props
For a jQuery solution look at Auto-size dynamic text to fill fixed size container
I was looking into this for work and I liked tnt-rox's answer, but I couldn't help but notice that it had some extra overhead that could be cut out.
document.body.setScaledFont = function(){
this.style.fontSize = (this.offsetWidth*0.35)+'%';
return this;
}
document.body.setScaledFont();
Cutting out the overhead makes it run a little bit quicker if you add it to an onresize event.
If you are only looking to have the font inside a specific element set to resize to fit, you could also do something like the following
window.onload = function(){
var scaledFont = function(el){
if(el.style !== undefined){
el.style.fontSize = (el.offsetWidth*0.35)+'%';
}
return el;
}
navs = document.querySelectorAll('.container>nav'),
i;
window.onresize = function(){
for(i in navs){
scaledFont(navs[i]);
}
};
window.onresize();
};
I just noticed nicolaas' answer also had some extra overhead. I've cleaned it up a bit. From a performance perspective, I'm not really a fan of using a while loop and slowly moving down the size until you find one that fits.
function setPageHeaderFontSize(selector) {
var $ = jQuery;
$(selector).each(function(i, el) {
var text = $(el).text();
if(text.length) {
var span = $("<span>").css({
visibility: 'hidden',
width: '100%',
position: 'absolute',
'line-height': '300px',
top: 0,
left: 0,
overflow: 'visible',
display: 'table-cell'
}).text(text),
height = 301,
fontSize = 200;
$(el).append(span);
while(height > 300 && fontSize > 10) {
height = span.css("font-size", fontSize).height();
fontSize--;
}
span.remove();
$(el).css("font-size", fontSize+"px");
}
});
}
setPageHeaderFontSize("#MyDiv");
And here is an example of my earlier code using jquery.
$(function(){
var scaledFont = function(el){
if(el.style !== undefined){
el.style.fontSize = (el.offsetWidth*0.35)+'%';
}
return el;
};
$(window).resize(function(){
$('.container>nav').each(scaledFont);
}).resize();
});
A bit late but this is how I approach this problem:
document.body.setScaledFont = function() {
var f = 0.35, s = this.offsetWidth, fs = s * f;
this.style.fontSize = fs + '%';
return this
}
document.body.setScaledFont();
The base document font is now set.
For the rest of your elements in the dom set font sizes as % or em and they will scale proportionately.
here I have a mootools solution:
Element.implement("fitText", function() {
var e = this.getParent();
var maxWidth = e.getSize().x;
var maxHeight = e.getSize().y;
console.log(maxWidth);
var sizeX = this.getSize().x;
var sizeY = this.getSize().y;
if (sizeY <= maxHeight && sizeX <= maxWidth)
return;
var fontSize = this.getStyle("font-size").toInt();
while( (sizeX > maxWidth || sizeY > maxHeight) && fontSize > 4 ) {
fontSize -= .5;
this.setStyle("font-size", fontSize + "px");
sizeX = this.getSize().x;
sizeY = this.getSize().y;
}
return this;
});
$$("span").fitText();
Here is another jQuery solution ...
/**
* Resizes page header font-size for the text to fit.
* basically we add a hidden span into the header,
* put the text into it and then keep reducing the super large font-size
* for as long as the height of the span exceeds the super
* tall line-height set for the test (indicating there is more than one line needed
* to show the text).
*/
function setPageHeaderFontSize(selectorString) {
jQuery(selectorString).each(
function(i, el) {
var text = jQuery(el).text();
var length = text.length;
if(length) {
var id = "TestToSeeLengthOfElement_" + i;
jQuery(el).append("<span style='visibility: hidden; width: 100%; position: absolute; line-height: 300px; top: 0; left: 0; overflow: visible; display: table-cell;' id='"+id+"'>"+text+"</span>");
var innerEl = jQuery("#"+id);
var height = 301;
var fontSize = 200;
while(height > 300 && fontSize > 10) {
height = jQuery(innerEl).css("font-size", fontSize).height();
fontSize--;
}
jQuery(innerEl).remove();
jQuery(el).css("font-size", fontSize+"px");
}
}
);
}
//you can run it like this... using any jQuery enabled selector string (e.g. h1.pageHeaders works fine).
setPageHeaderFontSize("#MyDiv");
Here's a way to find the height of the text that you are using.
It's simple and only uses javascript. You can use this to adjust your text relative to the height you want.
function getTextHeight(text, fontSize) {
var numberOfLines = 0;
var STL = text;
for(var i = 0; i < STL.length; i++){
if(STL[i] === '<'){
try{
if(STL[i + 1] === 'b' && STL[i + 2] === 'r' && STL[i + 3] === '>'){
numberOfLines++;
}
}
catch(err){
break;
}
}
return (numberOfLines + 1) * fontSize;
}