I want to make an image larger when the mouse is moved over it, and return it to normal after. The image loads at normal size fine using the getPhoto function in my JavaScript, but when I mouse over it, nothing happens.
What am I doing wrong?
document.getElementById("photo").onmouseover = function() {
mouseOver()
};
document.getElementById("photo").onmouseout = function() {
mouseOut()
};
function getPhoto(handle) {
var img = new Image();
var div = document.getElementById("photo");
while (div.firstChild) {
div.removeChild(div.firstChild);
}
img.src = "https://res.cloudinary.com/harmhxmnk/image/upload/" + handle;
img.height = 32;
img.onload = function() {
div.appendChild(img);
};
}
function mouseOver() {
var img = document.getElementById("photo");
img.height = 100;
}
function mouseOut() {
// TODO
}
.photo {
position: absolute;
top: 86px;
right: 92px;
}
<div class="photo" id="photo"></div>
No need for JS IMHO :-)
.photo {
position: absolute;
top: 86px;
right: 92px;
transform: scale(1);
transition: transform .5s;
}
.photo:hover {
transform: scale(1.2);
}
<div class="photo" id="photo"><img src="https://wallpaperbrowse.com/media/images/3848765-wallpaper-images-download.jpg" /></div>
None of the answers so far explain why it does not work. The reason it does not work is you are setting the height of 32 on the image. But when you are setting the height, you are setting it on the div, not the image. So if you want to do it your way, you would need to select the image. querySelector will let you reference the image in the element.
function mouseOver() {
var img = document.querySelector("#photo img");
img.height = 100;
}
I think it would be easier and cleaner to just use css for this
#photo:hover{
height: 100:
}
Very simple with CSS using flexbox (demo)
.col {
display: flex;
}
.col img {
margin: 5px 5px; /* more margin makes the image smaller */
flex-grow: 1;
}
.col img:hover {
margin: 0 0; /* less margin on hover makes the image bigger */
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col">
<img src="https://placekitten.com/g/200/200">
</div>
<div class="col">
<img src="https://placekitten.com/g/200/200">
</div>
</div>
<div class="row">
<div class="col">
<img src="https://placekitten.com/g/200/200">
</div>
<div class="col">
<img src="https://placekitten.com/g/200/200">
</div>
<div class="col">
<img src="https://placekitten.com/g/200/200">
</div>
</div>
</div>
Related
I have two divs, top and bottom. Both divs have dynamic height, the top div will show or hide depending on a variable.
I would like to add in a sliding animation to the top div when showing or hiding, but the bottom div should stick with the top div and slide with it too.
var hide = true;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (hide) {
topdiv.classList.add('hide');
} else {
topdiv.classList.remove('hide');
}
hide = !hide;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
}
.hide {
display: none !important;
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
I tried adding transform animations, but the effect is only applied to the top div while the bottom div remains unanimated.
#keyframes topDivAnimate {
from {
transform: translateY(-100%);
}
to {
transform:translateY(0%);
}
}
Help is much appreciated.
I would use CSS transition rather than animation. I've found it easiest to do by animating the lower div rather than the upper one, and changing its position so that it covers the top one (or, of course, not). See demonstration below, I've made as minimal changes as I could to the CSS and JS:
var cover = true;
var trigger = document.getElementById("trigger");
var bottomdiv = document.getElementsByClassName("body")[0];
trigger.addEventListener('click', function() {
if (cover) {
bottomdiv.classList.add('cover');
} else {
bottomdiv.classList.remove('cover');
}
cover = !cover;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
transform: translateY(0%);
transition: transform 0.5s;
}
.cover {
transform: translateY(-100%);
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
Are you looking something like this? Then please try this:
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if ($('#topdiv').css('display') == 'none') {
$(topdiv).slideDown();
} else {
$(topdiv).slideUp();
}
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
display: none;
background: #999;
}
.body {
background: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
Try this code and see if that's the effect you wanted. It uses the Animate.css library so you'll need to link that in your <head></head>
function animateCSS(element, animationName, callback) {
const node = document.querySelector(element)
node.classList.add('animated', animationName)
function handleAnimationEnd() {
node.classList.remove('animated', animationName)
node.removeEventListener('animationend', handleAnimationEnd)
if (typeof callback === 'function') callback()
}
node.addEventListener('animationend', handleAnimationEnd)
}
var hide = false;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (!hide) {
topdiv.classList.remove('hide');
animateCSS('.body', 'slideInDown');
animateCSS('#topdiv', 'slideInDown');
} else {
animateCSS('#topdiv', 'slideOutUp', function() {
topdiv.classList.add('hide');
})
animateCSS('.body', 'slideOutUp');
}
hide = !hide;
});
Working Codepen demo of my solution
Here's some more explanation on how to use the Animate.css library.
so I am trying to create the effect seen on this website (for the photos on the left side of the column):
https://www.franshalsmuseum.nl/en/
I want to be able to change the image on scroll inside of a div.
And preferably, it won't scroll down past the page until all of the images have been scrolled through!
I'm trying to get the hang of javascript before adding things like jQuery, so can someone help with this using pureJS?`
window.onscroll = function() {
console.log(window.pageYOffset);
var img1 = document.getElementById('img1');
var img2 = document.getElemebtById('img2')
if ( window.pageYOffset > 1000 ) {
img1.classList.add("hidden");
img2.classList.remove("hidden");
} else {
img2.classList.add("hidden");
img1.classList.remove("hidden");
}
}
.rightPhotos {
max-width: 50%;
height: 50%;
overflow: auto;
}
.aPhoto {
max-height: 100%;
}
.hidden {
visibility: hidden;
}
.images {
width: 100%;
height: 100%;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="IMAGES/sunglasses.jpeg" alt="Woman with Sunglasses">
</div>
<div class="aPhoto hidden">
<img class="images" src="IMAGES/dancer1.jpg" alt="A Dancer">
</div>
</div>
</div>
`
The page you linked actually looks very nice, so I took a while to make something looking a bit closer to it than what other answers do.
I added a properly working transition, similar to one on franshalsmuseum.nl.
I styled the page to deal relatively well with being resized:
The sizing of panes and images is all ralative,
Scroll steps are relative to page height,
Images are shown using <div> with background-image instead of <img> tag. Depending on the size of the window, they are slightly cropped to adjust to changing aspect ratio of viewport.
I made the number of image sets very simple to change. It could be improved by creating the html elements in Javascript, but that doesn't look necessary. At least, it wouldn't be for the original page.
How it works
HTML
Images are put into special envelop elements (.img-wrapper), that provide proper sizing and positioning position: relative is important there). Each image element gets url (as background image url) and image set number to be used by javascript:
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
Class visible is set to show imageset 1 at the beginning.
CSS
The key points are these definitions (and similar for #bottom-image). As the element enveloping the image has overflow: hidden, we can hide the image by moving it outside of visible area. When we set coordinates back to normal, the image will slide back, using the smooth transition.
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
JS
The Javascript code is very minimal, the interaction with DOM is really one line. However, it uses some tricks that may not be obvious, so there is this line with some links to documentation:
document.querySelectorAll('#left-pane .img').forEach((img) => {
img.classList.toggle('visible', img.dataset.imageset <= currentSet);
}
It just finds all images and adds or removes class visible depending on the data-imageset attribute of the image.
Full snippet with demo
See snippet below. Demo looks much better if you use "Full page" link after running the snippet.
let currentSet = 1;
function updateSelectedImgSet() {
const currentScroll = document.scrollingElement.scrollTop;
const scrollMax = document.scrollingElement.scrollHeight - document.scrollingElement.clientHeight;
const setsCount = 3;
const scrollPerSet = scrollMax / setsCount;
const scrolledSet = Math.floor(currentScroll / scrollPerSet) + 1;
if (scrolledSet == currentSet) {
return;
}
currentSet = scrolledSet;
document.querySelectorAll('#left-pane .img').forEach((img) => {
img.classList.toggle('visible', img.dataset.imageset <= currentSet);
});
}
window.onscroll = updateSelectedImgSet;
window.onresize = updateSelectedImgSet;
/* Left pane, fixed */
#left-pane {
position: fixed;
height: 100%;
width: 40vw;
}
#left-pane .img-wrapper {
position: relative;
height: 50%;
width: 100%;
overflow: hidden;
}
#left-pane .img-wrapper .img {
position: absolute;
width: 100%;
height: 100%;
/* Sizing and cropping of image */
background-position: center;
background-size: cover;
/* Transition - the slow sliding of images */
transition: 0.5s all ease-in-out;
}
/* hiding images in #top-image */
#left-pane #top-image .img {
top: 100%;
}
#left-pane #top-image .img.visible {
top: 0;
}
/* hiding images in #bottom-image */
#left-pane #bottom-image .img {
bottom: 100%;
}
#left-pane #bottom-image .img.visible {
bottom: 0;
}
/* Right pane, scrolling with the page */
#right-pane {
margin-left: 40vw;
}
.scrollable-content {
font-size: 40vw;
writing-mode: vertical-rl;
white-space: nowrap;
}
<div id="left-pane">
<div id="top-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/people');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/animals');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/any');">
</div>
</div>
<div id="bottom-image" class="img-wrapper">
<div class="img visible" data-imageset="1"
style="background-image: url('http://placeimg.com/640/480/nature');">
</div>
<div class="img" data-imageset="2"
style="background-image: url('http://placeimg.com/640/480/tech');">
</div>
<div class="img" data-imageset="3"
style="background-image: url('http://placeimg.com/640/480/arch');">
</div>
</div>
</div>
<div id="right-pane">
<div class="scrollable-content">Scrollable content!</div>
</div>
see code bellow:(I set 60 insteed 1000 (in function)for see changes)
I use one image and onscroll change the src of image
window.onscroll = function() {
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2')
if ( window.pageYOffset > 60 ) {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba2.jpg";
} else {
document.getElementById("img1").src = "https://material.angular.io/assets/img/examples/shiba1.jpg";
}
}
.rightPhotos
{
max-width: 50%;
height:50%;
overflow: auto;
}
.aPhoto
{
max-height: 100%;
}
.images
{
width: 100%;
height: 500px;
}
<div class="other">
<div class="rightPhotos" onscroll="myFunction()">
<div class="aPhoto">
<img class ="images" id="img1" src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Woman with Sunglasses"/>
</div>
</div>
</div>
You can use the CSS properties to show/ hide the elements; instead of having custom CSS with hidden class.
if ( window.pageYOffset > 1000 ) {
img1.style.visibility = 'hidden';
img2.style.visibility = 'visible';
} else {
img2.style.visibility = 'hidden';
img1.style.visibility = 'visible';
}
The above would hide the element, but the DOM element would still occupy space.
For it now to have space occupied (like to remove it)
if ( window.pageYOffset > 1000 ) {
img1.style.display = 'none';
img2.style.display = 'block';
} else {
img1.style.display = 'block';
img2.style.display = 'none';
}
//window.pageYOffset
var scrollingDiv = document.getElementById('scrollContainer');
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
scrollingDiv.onscroll = function(event) {
if (scrollingDiv.scrollTop < 500) {
img1.src = "https://placeimg.com/250/100/arch";
img2.src = "https://placeimg.com/250/100/animals";
}
if (scrollingDiv.scrollTop > 500) {
img1.src = "https://placeimg.com/250/100/nature";
img2.src = "https://placeimg.com/250/100/people";
}
if (scrollingDiv.scrollTop > 1000) {
img1.src = "https://placeimg.com/250/100/tech";
img2.src = "https://placeimg.com/250/100/any";
}
}
.container{
display: table;
width: 100%;
height: 100%;
}
body{
margin: 0;
}
.container > div {
vertical-align:top;
}
.left, .middle, .right {
display: table-cell;
height: 100vh;
box-sizing: border-box;
}
.left, .right{
width:40%;
background: gray;
}
.middle{
overflow: auto;
position: relative;
}
.in-middle{
background: tomato;
position: absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
margin: 0;
}
.in-in-middle{
height: 500px;
background: tomato;
}
.in-in-middle:nth-child(2){
background: pink;
}
.in-in-middle:nth-child(3){
background: skyblue;
}
.left img{
width: 100%;
transition: all 0.5s;
}
<div class="container">
<div class="left">
<img id="img1" src="https://placeimg.com/250/100/arch">
<img id="img2" src="https://placeimg.com/250/100/animals">
</div>
<div class="middle" id="scrollContainer">
<div class="in-middle">
<div class="in-in-middle" id="1"></div>
<div class="in-in-middle" id="2"></div>
<div class="in-in-middle" id="3"></div>
</div>
</div>
</div>
I am trying to achieve an effect of looping through images if a div is hovered or not.
If mouseenter div then cycle through images
if mouseleave div then stop cycling through images and remove all images (only background image will be visible).
currently I am using a setTimeout to fire itself recursively but I am having trouble with jquery on detecting if the mouse is hovering or left the object.
function logoImageLoop() {
$(".one-box .social_gallery .social_img:first").show().next(".social_img").hide().end().appendTo(".one-box .social_gallery");
};
var oneBoxIsHover = false;
$(".one-box").mouseenter(function(){
timeout();
function timeout() {
setTimeout(function(){
logoImageLoop();
timeout();
}, 100);
};
});
Here is a codepen for reference: http://codepen.io/H0BB5/pen/xEpqbv
A similar effect I am trying to achieve can be seen when hovering the cargo logo on this website: http://cargocollective.com/
You just need to clear the timer on mouseleave.
var timer = null;
$(".one-box").mouseenter(function(){
timeout();
function timeout() {
timer = setTimeout(function(){
logoImageLoop();
timeout();
}, 100);
};
}).mouseleave(function(){
clearTimeout(timer);
});
Here's a codepen: http://codepen.io/anon/pen/rrpwYJ
I would use an interval, and the JQuery .hover() functionality. Simply replacing your $(".one-box").mouseenter() with this will run the loop while you're hovered and remove it once your mouse leaves the area.
The important bit:
var imageChangeInterval;
$(".one-box").hover(function() {
imageChangeInterval = setInterval(function() {
logoImageLoop();
}, 100);
}, function() {
clearInterval(imageChangeInterval);
});
Full example:
function logoImageLoop() {
$(".one-box .social_gallery .social_img:first").show().next(".social_img").hide().end().appendTo(".one-box .social_gallery");
};
var oneBoxIsHover = false;
// New code:
var imageChangeInterval;
$(".one-box").hover(function() {
imageChangeInterval = setInterval(function() {
logoImageLoop();
}, 100);
}, function() {
clearInterval(imageChangeInterval);
});
.one-box {
position: relative;
height: 300px;
width: 300px;
}
.one-box a {
width: 100%;
}
.one-box a img {
max-width: 100%;
}
/* .social_img { display: none; } */
a#social_logo {
background-image: url(https://s3-us-west-2.amazonaws.com/staging-site-assets/one-method/instagram-logo.png);
background-repeat: no-repeat;
background-position: 0 0;
display: block;
position: absolute;
width: 73px;
height: 73px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 99;
}
.one_box .social_gallery {
position: absolute;
left: 0;
top: 0;
opacity: 1;
display: none;
}
.nav_logo .social_gallery .social_img {
position: absolute;
float: none;
margin: 0;
opacity: 1;
filter: alpha(opacity=100);
overflow: hidden;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one-box nav_logo">
<a id="social_logo" href="#" alt=""></a>
<div class="social_gallery img_wall gallery">
<div class="social_img wall_img">
<a class="social_link" href="#">
<img src="https://placeholdit.imgix.net/~text?txtsize=28&bg=222&txt=300%C3%97300&w=300&h=300" />
</a>
</div>
<div class="social_img">
<a class="social_link" href="#">
<img src="https://placeholdit.imgix.net/~text?txtsize=28&bg=fb2&txt=300%C3%97300&w=300&h=300" />
</a>
</div>
<div class="social_img">
<a class="social_link" href="#">
<img src="https://placeholdit.imgix.net/~text?txtsize=28&bg=777&txt=300%C3%97300&w=300&h=300" />
</a>
</div>
<div class="social_img">
<a class="social_link" href="#">
<img src="https://placeholdit.imgix.net/~text?txtsize=28&bg=fb2&txt=300%C3%97300&w=300&h=300" />
</a>
</div>
</div>
<div>
I'm trying to build a fluid mosaic grid. I used the fluid word since i already have a working mosaic grid.
You can check a fiddle i made on purpose for this question: https://jsfiddle.net/a995w8ye/
My HTML is:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Teste</title>
<link rel="stylesheet" href="style.css">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div id="divContainer">
<div id="1" class="cube">
</div>
<div id="2" class="cube">
</div>
<div id="3" class="cube">
</div>
<div id="4" class="cube">
</div>
<div id="5" class="cube">
</div>
<div id="6" class="cube">
</div>
<div id="7" class="cube">
</div>
<div id="8" class="cube">
</div>
<div id="9" class="cube">
</div>
</div> <!-- End of div container -->
</body>
</html>
CSS:
#divContainer {
width: 1000px;
height: 800px;
border: 1px solid black;
}
.cube {
position: relative;
float: left;
width: calc(1000px/3);
height: calc(800px/3);
cursor: pointer;
}
.cube.fullscreen{
z-index: 9;
width: 100%;
height: 100%;
position: relative;
background-color: #131313;
}
.cube:hover {
opacity: 0.75;
}
JS:
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function fillColors(){
for (var i = 1; i<=9; i++)
{
document.getElementById(i).style.background = getRandomColor();
}
}
window.onload=function(){
fillColors();
$('.cube').on('click', function() {
$(this).addClass('fullscreen');
$('.cube').each(function(){
if($(this).hasClass('fullscreen'))
{
return true;
}
$(this).hide();
})
})
}
The width and height if each cube are 1/3 of the main div. They are left float and they have a relative position. I need a relative position since the "divContainer" in the real case doesn't have a fixed size and in that case, since all cubes have exactly 1/3(width and height) of it they will make a perfect grid that can be 3x3 or even 1x9.
When a user click in a cube, that cube get's another class with a higher z-index and the width and heigh equal to his parent. The other cubes won't be visible in the end. They might or might not disappear. In the end I just want to see the expanded cube that i clicked.
This is simple. What i want to do is to make a cube expand slowly while the others vanish slowly as well or at least cover the others with a higher z-index. This is easy to achieve in the top left cube using .animate() but in the middle cube or the bottom right one i find difficult to do this.
P.S: ATM I'm not worried about everything come back to his original state. I just want to expand every div as mentioned.
Any suggestions?
Thanks in advance
UPDATE
I've fixed the code based on your comment
var container = $('#container'),
cubes = $('#container > div'),
count = 3, unit = 'vw',
fullstate = false;
function randomcolor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function fillcolor(){
$(this).css({background: randomcolor()});
}
function setup () {
var t = $(this),
i = t.index();
t.data({
top: Math.floor(i/count) * 100/count,
left: (i%count) * 100/count
});
}
function gridposition () {
var t = $(this);
t.css({
'z-index': 0,
top: t.data('top') + unit,
left: t.data('left') + unit,
width: 100/count + unit,
height: 100/count + unit
});
}
function fullcube () {
$(this).css({
'z-index': 9,
width: 100 + unit,
height: 100 + unit,
top: 0,
left: 0
});
}
cubes.each(function () {
setup.call(this);
fillcolor.call(this);
gridposition.call(this);
}).on('click', function () {
if (fullstate) {
cubes.each(gridposition);
} else {
fullcube.call(this);
}
fullstate = !fullstate;
});
html,
body,
#container,
#container > div.fullscreen {
width: 100%; height: 100%;
}
body {
margin: 0;
overflow-x: hidden;
}
#container > div {
position: absolute;
transition: all 0.5s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div></div> <div></div> <div></div>
<div></div> <div></div> <div></div>
<div></div> <div></div> <div></div>
</div>
OLD ANSWER
This is how I would solve this problem:
var container = $('#container'),
cubes = $('#container > div');
function randomcolor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function fillcolor(){
$(this).css({background: randomcolor()});
}
cubes.each(fillcolor).on('click', function () {
var h = 'hidden';
cubes.toggleClass(h);
$(this).removeClass(h).toggleClass('fullscreen');
});
html,
body,
#container,
#container > div.fullscreen {
width: 100%; height: 100%;
}
body {
margin: 0;
}
#container > div {
float: left;
width: 32vw; height: 32vw;
transition: all 0.5s;
}
#container > div:hover {
opacity: 0.75;
}
#container > div.hidden {
width: 0; height: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div></div> <div></div> <div></div>
<div></div> <div></div> <div></div>
<div></div> <div></div> <div></div>
</div>
I'm having difficulty figuring out how I could calculate the extra height of a div container caused by skewing it. I am masking an image inside the container and resizing it using a plugin.
The containers will not always have the same height and width so using fixed dimensions will not work.
Please see my demo.
http://jsfiddle.net/RyU9W/6/
HTML
<div id="profiles" class="container">
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/1200" alt="">
</div>
<div class="detail">
</div>
</div>
</div>
CSS
#profiles {
margin-top: 300px;
transform:skewY(-30deg);
-ms-transform:skewY(-30deg); /* IE 9 */
-webkit-transform:skewY(-30deg); /* Safari and Chrome */
}
.profile {
cursor: pointer;
float: left;
width: 32.25%;
margin: 0.5%;
position: relative;
}
.profile .image {
position: relative;
overflow: hidden;
height: 400px;
background: #000;
backface-visibility:hidden;
-webkit-backface-visibility:hidden; /* Chrome and Safari */
-moz-backface-visibility:hidden; /* Firefox */
-ms-backface-visibility:hidden; /* Internet Explorer */
}
.profile .image * {
position: relative;
transform:skew(0deg,30deg);
-ms-transform:skew(0deg,30deg); /* IE 9 */
-webkit-transform:skew(0deg,30deg); /* Safari and Chrome */
}
In skew we have a case of Right-angled triangle and the skew new width is equal to "Opposite" and we've the angle and the opposite so by this equation we can get the adjacent Opposite = Adjacent * tan(angle); Where opposite in case of skewX is the div height and in case of skewY will be the div width
Check this https://codepen.io/minaalfy/pen/exgvjb
function calculateSkew(){
var el = document.getElementById('bluebox');
var skewX = document.getElementById('skewX');
skewX.value = skewX.value || 0;
var skewY = document.getElementById('skewY');
skewY.value = skewY.value || 0;
var yRadians = skewY.value * Math.PI / 180;
var newHeight = el.offsetWidth * Math.tan(yRadians);
var calculatedHeight = el.offsetHeight + newHeight;
var xRadians = skewX.value * Math.PI / 180;
var newWidth = calculatedHeight * Math.tan(xRadians);
var calculatedWidth = el.offsetWidth + newWidth;
el.style.transform = ("skewX(" + skewX.value + "deg ) skewY(" + skewY.value + "deg )");
var output = document.getElementById('output');
output.innerHTML = "skewY by "+skewY.value+ " and new height calculated is "+calculatedHeight+ "<br> skewX by "+skewX.value+ " and the new calculated width is "+ calculatedWidth;
}
body {text-align:center}
#bluebox {width:100px;height:100px;background:blue;margin: 20px auto;}
<h4>Enter any numeric value for skewX or skewY to calculate the new width&height for the box</h4>
<div id="bluebox"></div>
<input type="number" placeholder="skewX" id="skewX" onkeyup="calculateSkew()" />
<input type="number" placeholder="skewY" id="skewY" onkeyup="calculateSkew()" />
<h1 id="output"></h1>
I got it using this solution.
var degrees = 30;
var radians= degrees*Math.PI/180;
var newHeight = parentWidth*Math.tan(radians);
var newOffset = newHeight / 2;
var parentHeight = parentHeight + newHeight;
Here is my updated fiddle with option to select degrees
http://jsfiddle.net/bhPcn/5/
Two functions that could help you.
function matrixToArray(matrix) {
return matrix.substr(7, matrix.length - 8).split(', ');
}
function getAdjustedHeight(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[2];
var adjusted = Math.sin(alpha)*origWidth/Math.sin(Math.PI/2-alpha);
return origHeight+Math.abs(adjusted);
}
function getAdjustedWidth(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[1];
var adjusted = Math.sin(alpha)*origHeight/Math.sin(Math.PI/2-alpha);
return origWidth+Math.abs(adjusted);
}
Usage (http://jsfiddle.net/x5her/18/):
// if you use scewY
console.log(getAdjustedWidth($(".image")[0]))
// if you use scewX
console.log(getAdjustedHeight($(".image")[0]))
Example of dynamic skew angle depending on the height.
In angular:
// We use a mathematical expression to define the degree required in skew method
// The angle depend on the height and width of the container
// We turn the answer from atan which is in radian into degrees
//
// DEGREES = RADIAN * 180 / PI
const degrees = Math.atan(
parent.nativeElement.clientWidth / parent.nativeElement.clientHeight
) * 180 / Math.PI;
parent.nativeElement.children[0].style.transform = `skew(${degrees}deg)`;
parent.nativeElement.children[1].style.transform = `skew(${degrees}deg)`;
In Jquery for the snippet :
$(document).ready(() => {
const parent = $('.duo:first');
const degrees = Math.atan(parent.width() / parent.height()) * 180 / Math.PI;
$('.first').css('transform', `skew(${degrees}deg)`);
$('.second').css('transform', `skew(${degrees}deg)`);
});
.container {
width: 10em;
height: 10em;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.one-square {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
}
.duo {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
flex-direction: row;
position: relative;
overflow: hidden;
}
.first {
width: 100%;
height: 100%;
background-color: red;
transform: skew(0deg);
transform-origin: 0 0;
position: absolute;
}
.second {
width: 100%;
height: 100%;
background-color: yellow;
transform: skew(0deg);
transform-origin: 100% 100%;
position: absolute;
}
.a {
background-color: grey;
}
.b {
background-color: green;
}
.c {
background-color: lightgrey;
}
.d {
background-color: #444444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="one-square a"></div>
<div class="one-square b"></div>
<div class="duo">
<div class="first">
</div>
<div class="second">
</div>
</div>
<div class="one-square c"></div>
<div class="one-square d"></div>
</div>
Now that it's 2021, just use el.getBoundingClientRect().height. It takes css transform into its calculations.