I’m creating a JS slider for before and after of the images. I have the following HTML, JS and CSS:
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="mainSection">
<div id="one" class="bal-container">
<div class="bal-after">
<img src="https://i.imgur.com/UhD5VoC.png">
<div class="bal-afterPosition afterLabel">
After
</div>
</div>
<div class="bal-before">
<div class="bal-before-inset">
<img src="https://i.imgur.com/lQRgFqb.png">
<div class="bal-beforePosition beforeLabel">
Before
</div>
</div>
</div>
<div class="bal-handle">
<span class=" handle-left-arrow"></span>
<span class="handle-right-arrow"></span>
</div>
</div>
</div>
<script>
class BeforeAfter {
constructor(enteryObject) {
const beforeAfterContainer = document.querySelector(enteryObject.id);
const before = beforeAfterContainer.querySelector('.bal-before');
const beforeText = beforeAfterContainer.querySelector('.bal-beforePosition');
const afterText = beforeAfterContainer.querySelector('.bal-afterPosition');
const handle = beforeAfterContainer.querySelector('.bal-handle');
var widthChange = 0;
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
window.onresize = function () {
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
}
before.setAttribute('style', "width: 50%;");
handle.setAttribute('style', "left: 50%;");
//touch screen event listener
beforeAfterContainer.addEventListener("touchstart", (e) => {
beforeAfterContainer.addEventListener("touchmove", (e2) => {
let containerWidth = beforeAfterContainer.offsetWidth;
let currentPoint = e2.changedTouches[0].clientX;
let startOfDiv = beforeAfterContainer.offsetLeft;
let modifiedCurrentPoint = currentPoint - startOfDiv;
if (modifiedCurrentPoint > 10 && modifiedCurrentPoint < beforeAfterContainer.offsetWidth - 10) {
let newWidth = modifiedCurrentPoint * 100 / containerWidth;
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index: 1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
});
});
//mouse move event listener
beforeAfterContainer.addEventListener('mousemove', (e) => {
let containerWidth = beforeAfterContainer.offsetWidth;
widthChange = e.offsetX;
let newWidth = widthChange * 100 / containerWidth;
if (e.offsetX > 10 && e.offsetX < beforeAfterContainer.offsetWidth - 10) {
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index:" + "1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
})
}
}
</script>
<script>
new BeforeAfter({
id: '#one'
});
</script>
</body>
</html>
style.css
@media all and (max-width: 479px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 700px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (max-width: 599px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 800px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 480px) and (max-width: 768px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1000px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 768px) and (max-width: 959px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1100px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 960px) and (max-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
@media all and (min-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
/* Before After Container */
.bal-container {
position: relative;
width: 100%;
height: 100%;
cursor: grab;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.bal-after {
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.bal-before {
display: block;
position: absolute;
top: 0;
/* right: 0; */
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 15;
overflow: hidden;
}
.bal-before-inset {
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
.bal-after img,
.bal-before img {
object-fit: cover;
position: absolute;
width: 100%;
height: 100%;
object-position: 50% 50%;
top: 0;
bottom: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.bal-beforePosition {
background: #121212;
color: #fff;
left: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.bal-afterPosition {
background: #121212;
color: #fff;
right: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.beforeLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.afterLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
/* handle and arrow */
.bal-handle {
height: 41px;
width: 41px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -20px;
margin-top: -21px;
border: 2px solid #fff;
border-radius: 1000px;
z-index: 20;
pointer-events: none;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.handle-left-arrow,
.handle-right-arrow {
width: 0;
height: 0;
border: 6px inset transparent;
position: absolute;
top: 50%;
margin-top: -6px;
}
.handle-left-arrow {
border-right: 6px solid #fff;
left: 50%;
margin-left: -17px;
}
.handle-right-arrow {
border-left: 6px solid #fff;
right: 50%;
margin-right: -17px;
}
.bal-handle::before {
bottom: 50%;
margin-bottom: 20px;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.bal-handle::after {
top: 50%;
margin-top: 20.5px;
box-shadow: 0 0 5px rgb(12, 12, 12);
}
.bal-handle::before,
.bal-handle::after {
content: " ";
display: block;
width: 2px;
background: #fff;
height: 9999px;
position: absolute;
left: 50%;
margin-left: -1.5px;
}
The problem is that what I have at the moment zooms on the images and the images are not fully visible. For example, I use the following two images which are about 587×600 in dimension: https://imgur.com/a/YDdaZYR
Any ideas how to make sure that the mainSection
div adjusts itself according to the images to make them fully visible (it is okay if the images are scaled down to certain dimension as long as they fully fit and are nice looking).
2
Answers
As you want to resize the
mainSection
according to the size of the images, here, I am tracking the height and width of the first image and setting these values to themainSection
. Works as you wanted.You can tweak around with the
object-fit
of the.bal-after img
&.bal-before img
to becontain
instead ofcover
, and then adjust theheight
of the container, accordingly. Somehow, like this: