Horizontal Smooth Momentum Scrolling - javascript

THE PROBLEM: I need to apply some mouse wheel smooth horizontal scrolling to this layout: https://jsfiddle.net/38qLnzkh/.
ALTERNATIVE: I've found this Script that does exactly what I want but it seems to work only vertically: Butter.js. If you can make it work Horizontally it would probably solve all my problems.
IMPORTANT:
1. The Script should be disabled based on screen width and in touch devices.
2. It should accommodate a menu on top of everything like you seen in the fiddle.
Thank you in advance.
EDIT:
In case it's not clear what I need, here are two examples with the effect I'm looking for:
https://nemesiscorporation.com/
https://www.tentwenty.me/about-us
MY LAYOUT:
HTML:
<main class="outer-wrapper">
<div class="wrapper">
<article class="section" id="a"><h2>01</h2></article>
<article class="section" id="b"><h2>02</h2></article>
<article class="section" id="c"><h2>03</h2></article>
<article class="section" id="d"><h2>04</h2></article>
<article class="section" id="e"><h2>05</h2></article>
<article class="section" id="f"><h2>06</h2></article>
</div>
</main>
CSS:
.outer-wrapper {
width: auto;
height: 100vw;
transform: rotate(-90deg) translateX(-100vh);
transform-origin: top left;
overflow-y: scroll;
overflow-x: hidden;
position: absolute;
scrollbar-width: none;
-ms-overflow-style: none;
}
::-webkit-scrollbar {
display: none;
}
.wrapper {
display: flex;
flex-direction: row;
width: auto;
transform: rotate(90deg) translateY(-100vh);
transform-origin: top left;
margin: 0;
padding: 0;
}
.section {
color: #000;
width: 100vw;
height: 100vh;
}

I've published an API on github that can easily solve this problem, below you'll find the code to do what you want.
Compared to yours I've just added the js code and the <script> in the HTML.
If you want to know more about it, here you can find the documentation.
EDIT
Since the requirements have changed a little bit and the API has been updated I've modified the example below so that it better fits the question.
Main changes to the answer:
Now the js is inside a init() method called onload
The css styles have been modified (transform:rotate brakes most of scrolling APIs)
The support for the navbar's smooth scroll has been added
The scrolling amount now depends on how much the user physically scrolls the mousewheel
/* UPDATED 2022 ANSWER */
function init() {
/*
* Variables preparation
*/
let yourWrapperElement = document.getElementsByClassName("outer-wrapper")[0];
let whateverEaseFunctionYouWant = remaningScrollDistance => { return remaningScrollDistance / 15 + 1 };
//Added support for navbar menu's smooth scrolling
uss.hrefSetup();
/*
* As you asked for, we only apply the custom scrolling for desktop devices
* by using the "wheel" event instead of the "scroll" or "touchmove" events.
*/
yourWrapperElement.addEventListener("wheel", event => {
/*
* We want to overwrite the default scrolling behaviour
* of your outer-wrapper component.
*/
event.preventDefault();
event.stopPropagation();
uss.scrollXBy(event.deltaY, yourWrapperElement, null, false);
}, {passive:false});
/*
* We apply a the custom ease function
* which will be used whenever our component is scrolled by the API
*/
uss.setXStepLengthCalculator(whateverEaseFunctionYouWant, yourWrapperElement);
}
body {
margin: 0;
padding: 0;
}
.outer-wrapper {
width: auto;
height: 100vh; /* Changed to vh */
width: 100vw; /* Added */
/*transform: rotate(-90deg) translateX(-100vh); ROTATING containers brakes 90% of scrolling APIs
transform-origin: top left;*/
overflow-y: scroll;
overflow-x: hidden;
position: absolute;
scrollbar-width: none;
-ms-overflow-style: none;
/*scroll-behavior: smooth; ISN'T NEEDED FOR MY API */
}
::-webkit-scrollbar {
display: none;
}
.wrapper {
display: flex;
flex-direction: row;
/*width: auto; NOT NEEDED IF WE USE FLEX-SHRINK 0
transform: rotate(90deg) translateY(-100vh); ROTATING containers brakes 90% of scrolling APIs
transform-origin: top left;*/
margin: 0; /* not really needed */
padding: 0; /* not really needed */
}
.section {
color: #000;
flex-shrink: 0; /* ADDED insted of the width/height of the wrapper */
width: 100vw;
height: 100vh;
}
#a { background-color: #ccc; }
#b { background-color: #fff; }
#c { background-color: #ccc; }
#d { background-color: #fff; }
#e { background-color: #ccc; }
#f { background-color: #fff; }
h2 {
text-align: center;
font-size: 200px;
margin: 0;
}
/* MENU _________________________ */
.logo {
float: left;
}
nav {
width: 100%;
}
/* HEADER */
header {
float: left;
width: 100%;
position: absolute;
z-index: 9999;
}
/* HEADER LARGE */
header.large {
height: 50px;
}
header.large .logo {
width: 225px;
height: 50px;
margin: 20px 0 0 20px;
background: url('../images/logo-fireqa-green-500px.png');
background-repeat: no-repeat;
background-size: contain;
transition: 0.7s all;
-moz-transition: 0.7s all;
-webkit-transition: 0.7s all;
-o-transition: 0.7s all;
}
/* UNORDERED LIST */
header.large ul {
list-style: none;
float: right;
margin-right: 25px;
}
header.small ul {
list-style: none;
float: right;
margin: 0;
}
header.large li {
display: inline;
float: left;
list-style-position: inside;
height: 50px;
-webkit-transition: all ease 0.3s;
-moz-transition: all ease 0.3s;
transition: all 0.3s ease-in-out;
}
header.large li a {
display: block;
padding: 20px;
color: #0E6245;
text-decoration: none;
font-family: 'Montserrat', 'arial', sans-serif;
font-weight: 600 !important;
letter-spacing: -1px;
font-size: 25px;
background-image: linear-gradient(#0E6245, #0E6245);
background-position: 50% 80%;
background-repeat: no-repeat;
background-size: 0% 4px;
-moz-transition: all 0.3s ease-in-out 0s;
-ms-transition: all 0.3s ease-in-out 0s;
-o-transition: all 0.3s ease-in-out 0s;
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
header.large li a:hover, a:focus {
background-size: 60% 4px;
}
<script src = "https://cdn.jsdelivr.net/npm/universalsmoothscroll#latest/universalsmoothscroll-min.js"></script>
<body onload = init()>
<main class="outer-wrapper">
<div class="wrapper">
<article class="section" id="a"><h2>01</h2></article>
<article class="section" id="b"><h2>02</h2></article>
<article class="section" id="c"><h2>03</h2></article>
<article class="section" id="d"><h2>04</h2></article>
<article class="section" id="e"><h2>05</h2></article>
<article class="section" id="f"><h2>06</h2></article>
</div>
</main>
<!-- MENU _____________________ -->
<header class="large">
<div class="container">
<nav>
<a><div class="logo"></div></a>
<ul>
<li>01</li>
<li>02</li>
<li>03</li>
<li>04</li>
</ul>
</nav>
</div>
</header>
</body>
</html>

There is a nice package called smooth-scrollbar.
I've adjusted your example. It disables smooth scrolling for mobile devices, but otherwise it's just calling the package. And I've cleaned up some CSS.
/** #see https://stackoverflow.com/a/52855084/5312432 */
function isTouchDevice() {
return window.matchMedia("(pointer: coarse)").matches;
}
function initSmoothScrolling() {
const options = {
damping: 0.1,
alwaysShowTracks: true
};
const elements = document.querySelectorAll(".smooth-scrollbar");
for (const element of elements) {
Scrollbar.init(element, options);
}
}
if (!isTouchDevice()) {
initSmoothScrolling();
}
body {
margin: 0;
padding: 0;
}
.smooth-scrollbar {
overflow: auto;
}
.wrapper {
display: flex;
flex-direction: row;
}
.section {
width: 100vw;
height: 100vh;
flex-shrink: 0;
}
.section:nth-child(odd) {
background-color: #ccc;
}
.section:nth-child(even) {
background-color: #fff;
}
h2 {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-size: 200px;
margin: 0;
}
<main class="smooth-scrollbar">
<div class="wrapper">
<article class="section"><h2>01</h2></article>
<article class="section"><h2>02</h2></article>
<article class="section"><h2>03</h2></article>
<article class="section"><h2>04</h2></article>
<article class="section"><h2>05</h2></article>
<article class="section"><h2>06</h2></article>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/smooth-scrollbar/8.5.3/smooth-scrollbar.js"></script>

Related

CSS & Javascript issues with a hamburger menu and an image gallery

I was following 2 youtube tutorials while working on a website. One tutorial was on building a complete website that's responsive and the second was on creating an image gallery with a grid layout. The end result that I had when I finished working on my website looked good but I noticed two problems.
When you decrease the size of the website so that it takes up half of your screen, the navbar shrinks down and you get a hamburger menu. But clicking on the hamburger isn't opening it up like it should. There's an eventListener that should be adding and removing a class called active but nothing is happening.
This is the html code that contains the navbar and hamburger icon
<header>
Glitta Art Studio
<div class="bx bx-menu" id="menu-icon"></div>
<ul class="navbar">
<li>Home</li>
<li>About</li>
<li>Gallery</li>
<li>Contact</li>
</ul>
</header>
This is the CSS for the media query
#media(max-width: 1140px) {
section {
padding: 50px 8%;
}
#menu-icon {
display: initial;
color: var(--text-color);
}
header .navbar {
position: absolute;
top: -400px;
left: 0;
right: 0;
display: flex;
flex-direction: column;
text-align: center;
background: #2b2640;
transition: .3s;
}
header .navbar .active {
top: 70px;
}
.navbar a {
padding: 1.5rem;
display: block;
}
.col {
width: 50%;
margin-bottom: 10px;
}
}
And here's the JavaScript
let menu = document.querySelector("#menu-icon");
let navbar = document.querySelector(".navbar");
menu.addEventListener("click", function () {
navbar.classList.toggle("active")
});
window.onscroll = () => {
navbar.classList.remove("active");
};
The second problem is technically not as big of a deal as the nav, but it's been more annoying for me to deal with so far. When you move your mouse over one of the images in the gallery section, a white box appears over the image with a title of the image and some information about it. But for some reason, the person in the tutorial added an a tag to the text in these boxes and I blindly added that to my project without thinking. Clicking on the box brings you back up to the homepage so I want to get rid of that completely and not have it link to anything. I'm not sure what the issue is with the CSS, but if you try to remove the a tags in the html and replace them with a regular p tag then it completely ruins the the grid of images and they all get stuck on one side of the screen.
Here's the HTML code of the gallery (There's 10 divs exactly like this with the same filler text and temporary image)
<div class="image-gallery">
<div class="image-box">
<img src="img/paintbrush.jpeg" alt="paintbrush">
<div class="overlay">
<div class="details">
<h3 class="title">
Painting Title
</h3>
<span class="category">
text about piece here
</span>
</div>
</div>
</div>
<div class="image-box">
<img src="img/paintbrush.jpeg" alt="paintbrush">
<div class="overlay">
<div class="details">
<h3 class="title">
Painting Title
</h3>
<span class="category">
text about piece here
</span>
</div>
</div>
</div>
And here's the CSS
.gallery {
margin: 0;
padding: 0;
position: relative;
}
.image-gallery {
width: 100%;
max-width: 950px;
margin: 0 auto;
padding: 50px 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px,1fr));
grid-auto-rows: 250px;
grid-auto-flow: dense;
grid-gap: 20px;
}
.image-gallery .image-box {
position: relative;
background-color: #d7d7d8;
overflow: hidden;
}
.image-gallery .image-box:nth-child(7n + 1){
grid-column: span 2;
grid-row: span 2;
}
.image-gallery .image-box img {
width: 100%;
height: 100%;
object-fit: cover;
transition: all 0.5s ease;
}
.image-gallery .image-box:hover img {
transform: scale(1.1);
}
.image-gallery .image-box .overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #fafaf2;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: all 0.5s ease;
z-index: 1;
}
.image-gallery .image-box:hover .overlay {
top: 20px;
right: 20px;
bottom: 20px;
left: 20px;
opacity: 1;
}
.image-gallery .image-box .details {
text-align: center;
}
.image-gallery .image-box .details .title {
margin-bottom: 8px;
font-size: 24px;
font-weight: 600;
position: relative;
top: -5px;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.image-gallery .image-box .details .category {
font-size: 18px;
font-weight: 400;
position: relative;
bottom: -5px;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.image-gallery .image-box:hover .details .title {
top: 0px;
opacity: 1;
visibility: visible;
transition: all 0.3s 0.2s ease;
}
.image-gallery .image-box:hover .details .category {
bottom: 0;
opacity: 1;
visibility: visible;
transition: all 0.3s 0.2s ease;
}
.image-gallery .image-box .details .title a,
.image-gallery .image-box .details .category a {
color: #222222;
text-decoration: none;
}
Sorry for asking these basic questions. I haven't practiced coding anything in a long while so I've forgotten a lot of things.
Edit: I was able to fix the gallery issue. Now its just the hamburger issue that I have to deal with
You can try implying the function in the HTML element itself like this:
<div class="bx bx-menu" id="menu-icon" onclick="ToggleClassActive()"></div>
and you need to delete the eventlistener function and use this instead
function ToggleClassActive(){
let menu = document.querySelector("#menu-icon");
let navbar = document.querySelector(".navbar");
navbar.classList.toggle("active");
}
You also need to ensure that the script is after the elements(The best place to place your script is right before the
And could you please show the error which occurs in the console

Image slides that fades when navbar is hit

I'm trying to make a replica of the slider on top of this google page: https://www.google.com/doodles
If someone could make a replica of the image slider with the bars, that would be great! I've tried to on my own but can't figure it out. Here's my try if it's helpful!
JAVASCRIPT:
<script>
var imgArray = [
'images/img1.gif',
'images/img2.gif',
'images/img3.jpg',
'images/img4.jpg'],
curIndex = 0;
imgDuration = 3000;
function slideShow() {
document.getElementById('slider').className += "fadeOut";
setTimeout(function () {
document.getElementById('slider').src = imgArray[curIndex];
document.getElementById('slider').className = "";
}, 500);
curIndex++;
if (curIndex == imgArray.length) { curIndex = 0; }
}
</script>
HTML:
<img class="slidershow" id="slider" src="images/img1.gif" onmouseover="slideShow()">
<div id="navigation">
<label for="r1" class="bar" id="bar1"></label>
<label for="r2" class="bar" id="bar2"></label>
<label for="r3" class="bar" id="bar3"></label>
<label for="r4" class="bar" id="bar4"></label>
</div>
</div>
CSS: --> Honestly, I wrote so much CSS that I don't know which ones relate, so I might have left a few out. Need to clean that up - Apologize in advance
.nav_links {
list-style: none;
}
.nav_links li {
display: inline-block;
padding: 0px 20px;
}
.nav_links li a {
color: #009cdc;
transition: all 0.3s ease 0s;
}
.nav_links li:hover a {
color: #2772ff;
}
#top-content {
display: block;
}
latest-nav li#latest-nav-1 {
background-color: #fa4842;
}
#latest-nav li.off {
border-top: 15px solid #fff;
}
#latest-nav li.off {
height: 5px;
opacity: 0.35;
}
#latest-nav li {
cursor: pointer;
float: left;
height: 5px;
transition: opacity 0.15s ease,height 0.15s ease,border-top 0.15s ease;
-moz-transition: opacity 0.15s ease,height 0.15s ease,border-top 0.15s ease;
-webkit-transition: opacity 0.15s ease,height 0.15s ease,border-top 0.15s ease;
width: 16.6%;
}
.slidershow {
height: 400px;
overflow: hidden;
}
.middle {
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%,-50%);
}
#navigation {
position: absolute;
bottom: 35px;
left: 60%;
transform: translateX(-50%);
display: flex;
}
.bar {
border-top: 15px solid #fff;
width: 200px;
opacity: 0.35;
height: 5px;
cursor: pointer;
transition: 0.4s;
}
.slides {
width: 500%;
height: 100%;
display: flex;
margin-top: 30px;
}
.slide {
width: 20%;
transition: 0.6s;
}
.slide img {
display: block;
margin: auto;
max-height: 250px;
max-width: 600px;
width: auto;
}
latest .container img {
display: block;
margin: auto;
max-height: 250px;
max-width: 600px;
}
#bar1 {
background-color: #3875fc;
}
#bar2 {
background-color: #ff8809;
}
#bar3 {
background-color: #19be29;
}
#bar4 {
background-color: #fa4842;
}
Thanks so much!
I'm always happy to see newcomers devoting time to study. First of all, good job! Unfortunately I'm not a very good teacher, but I put together a little example of this slider you're working on. You can check it clicking here.
Basically what is going on is:
The HTML is divided into two sections: the slider & the navbar.
I hide all slides by default applying a display: none to them. They're only visible when I add an additional class.
Detect the hover method via javascript. Whenever the navbar item is hovered on, you will detect its position (I added a data attribute called data-position to find out which position it is) and show the correspondent slider.
So, if the navbar has the data-position of 2, I know that I must show the second slide. To do that, I use .slider .slider-item:nth-child(2).
As I mentioned I'm not the best at explaining, but I hope this helps you out a little bit. Keep studying and don't give up!
HTML:
<div class="wrapper">
<div class="slider">
<div class="slider-item slider-item--visible">
hello item 1
</div>
<div class="slider-item">
hello item 2
</div>
<div class="slider-item">
hello item 3
</div>
</div>
<nav class="navbar">
<span class="navbar-item navbar-item--selected" data-position="1"></span>
<span class="navbar-item" data-position="2"></span>
<span class="navbar-item" data-position="3"></span>
</nav>
</div>
CSS
.wrapper{
max-width: 1000px;
width: 100%;
margin: 0 auto;
display: block;
}
/* Slider */
.slider{
max-width: 100%;
width: 100%;
}
.slider-item{
display: none;
}
.slider-item--visible{
display: block;
}
/* Navbar */
.navbar{
max-width: 100%;
display: flex;
align-items: flex-end;
height: 8px;
}
.navbar-item{
max-width: 33.3%;
width: 100%;
display: block;
height: 5px;
cursor: pointer;
opacity: .5;
transition: all .32s ease;
}
.navbar-item--selected{
height: 8px;
opacity: 1;
}
/* Meaningless styles (colors) */
.navbar-item:nth-child(1){
background: salmon;
}
.navbar-item:nth-child(2){
background: lightblue;
}
.navbar-item:nth-child(3){
background: #19be29;
}
Javascript
const $navbars = document.querySelectorAll(`.navbar-item`);
function removeSelected(){
const $selected = document.querySelectorAll(`.navbar-item--selected, .slider-item--visible`);
if (!$selected){
return;
}
for (let each of $selected){
each.classList.remove("navbar-item--selected");
each.classList.remove("slider-item--visible");
}
}
for (let each of $navbars){
each.addEventListener("mouseover", function(){
removeSelected();
const position = each.getAttribute("data-position");
const $item = document.querySelector(`.slider .slider-item:nth-child(${position})`)
each.classList.add("navbar-item--selected")
$item.classList.add("slider-item--visible");
});
}

CSS Typing Effect not spanning multiple lines

I have had a look around this site and can't seem to find a fix for this issue.
I have this typing effect that scrolls through various sentences in an array, I need it to wrap onto a second line whenever it reaches a certain width but if I remove the white-space: wrap you can see all of the text just on multiple lines and it expands the width slowly, I need it to only wrap after a certain width is reached.
I tried adding white-space: wrap at a certain point in the animation, however, this doesn't seem to have the desired effect.
Code here:
.type-container {
min-height: 100vh;
background: #000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
position: relative;
}
.content {
color: var(--white);
margin: 0 auto;
width: 28%;
}
ul li {
display: inline-block;
overflow: hidden;
height: 100px;
font-size: 29px;
position: absolute;
left: 36%;
box-sizing: border-box;
animation: typing 5s steps(100, end) infinite;
white-space: nowrap;
}
#cursor {
display: inline-block;
vertical-align: middle;
width: 3px;
height: 34px;
background: var(--white);
animation: blink 1s steps(100, end) infinite;
margin-left: 3px;
}
#keyframes typing {
0% {
width: 0%;
}
50% {
width: 100%;
}
100% {
width: 0%;
}
}
#keyframes blink {
0% {
background: transparent;
}
50% {
background: var(--white);
}
}
<div className="type-container">
<div className="content">
<h1 className="heading-1">
Our Management Team has over 50 years of experience:
</h1>
<div className="typed-section">
<ul className="heading-2">
<li id="typed-word">
{sentence}
<div id="cursor" />
</li>
</ul>
</div>
</div>
</div>

addEventListener adds incorrect properties on click - only on 320x480

TL DR it should be display: flex; opacity: 1
I have a menu which works in the following way:
On mouseenter or click, the menu is shown (display: flex, opacity: 1)
On mouseleave or click (outside the menu area) the menu is hidden (display: none, opacity: 0)
The problem occures when I try to "open" the menu in the Dev. Tools on 320x480 resolution.
When I click on the menu area, only #envelope does the transformation. #links (should also transform but don't becouse of the following reasons) which should get display: flex actually gets display: none assigned to it.
Note: It's working in full screen. Something is bothering him with the 320x480 res.
If I can elaborate or provide any additional information, let me know.
Thank you
function hide (){
document.getElementById("links").style.display = "none";
};
function show (){
document.getElementById("links").style.display = "flex";
document.getElementById("links").style.opacity = "1";
};
var menu = document.getElementById("menu");
menu.addEventListener("mouseenter", show);
menu.addEventListener("mouseleave", hide);
menu.addEventListener("click", show);
document.addEventListener("click", function (){
if (this != menu){
document.getElementById("links").style.display="none";
}
});
#menu{
height: 10vh;
background-color: red;
text-align: center;
transition: all 1s ease-out;
padding-top: 5vh;
}
#menu:hover{
color: red;
}
#envelope{
height: 0;
display: block;
background-color: blue;
min-width: 100%;
z-index: 1;
position: absolute;
left: 0;
content: "";
opacity: 0;
transition: all 1.3s ease-out;
}
#links{
height: 0;
display: none;
background-color: pink;
justify-content: center;
z-index: 2;
min-width: 100%;
opacity: 0;
transition: all 1s ease-in;
}
#google{
margin-top: -1vh;
width: 150px;
}
#mysite{
padding-left: 5%;
margin-top: -1vh;
width: 150px;
}
#menu:hover #envelope{
height: 100px;
opacity: 1;
}
#menu:focus #envelope{
height: 100px;
opacity: 1;
}
#menu:hover #links{
opacity: 1;
height: 300px;
}
#menu:focus #links{
opacity: 1;
height: 300px;
}
<div id="menu">Click here to browse the internet.
<div id="envelope">
<div id="links" >
<div><img id="google" src="https://seomofo.com/wp-content/uploads/2010/05/google_logo_new.png" /></div>
<div style="width: 20%;"></div>
<div><img id="mysite" src="https://toppng.com/uploads/preview/wwf-logo-horizontal-world-wildlife-foundation-logo-shirt-11563219164hg5hfcveei.png"/></div>
</div>
</div>
</div>
Don't use transition: all because the browser then need to loop through all properties, and it might cause lag.
Don't use position: absolute unless you have to.
I removed #envelope and inserted the "Click here ..." text in a label (explanation why below).
I arranged classes so I didn't have to repeat code.
Pure CSS solution below.
I made a little CSS hack, where I used a label and a checkbox to simulate a click. So when clicking on the label#menu-toggler, the (hidden) checkbox is checked, which triggers #menu-toggler:checked ~ #links.invisible. I had to add another class to #links, otherwise the low specificity wouldn't trigger the change.
html, body { /* new */
margin: 0px;
padding: 0px;
}
#menu {
height: 15vh; /* changed */
background-color: red;
text-align: center;
margin: 0.5rem; /* new */
}
#menu > input#menu-toggler { /* new */
display: none;
}
#menu > .tagline { /* new */
display: block; /* to get padding to work */
padding: 5vh 0px;
transition: opacity 1s;
}
#menu:hover > .tagline { /* new */
opacity: 0;
}
#menu > .tagline, /* new */
#menu > #links /* new */
{
transition-timing-function: ease-out;
}
#menu > #links {
display: flex;
justify-content: space-around; /* changed */
position: relative; /* changed */
left: -0.5rem; /* changed */
top: -5vh; /* changed */
opacity: 0;
height: 0;
width: 100vw; /* changed */
z-index: 1;
overflow: hidden; /* new */
background-color: pink;
transition-property: height, opacity;
transition-duration: 1.3s;
}
#menu:hover #links,
#menu-toggler:checked ~ #links.invisible { /* new */
height: 150px !important; /* changed */
opacity: 1 !important;
}
#links #google,
#links #mysite
{
width: 150px;
}
<div id="menu">
<input id="menu-toggler" type="checkbox" />
<label for="menu-toggler" class="tagline">Click here to browse the internet.</label>
<div id="links" class="invisible">
<div><img id="google" src="https://seomofo.com/wp-content/uploads/2010/05/google_logo_new.png" /></div>
<div><img id="mysite" src="https://toppng.com/uploads/preview/wwf-logo-horizontal-world-wildlife-foundation-logo-shirt-11563219164hg5hfcveei.png"/></div>
</div>
</div>

Responsive Hover Box over Responsive Image

I've been using a tutorial for making a hover box go over a set of images.
The article can be found here.
Got it working perfectly, except I want my images and the hover to be responsive to window size (just via width is fine), I've tried looking up how to do this. Seems like it might be a case of using % rather than a fixed value, but not experienced enough to know how to execute the markup. Even if I get the images to re-size the hover box doesn't re-size with them.
Is it possible to add something to the existing CSS to make this happen.
ul.img-list {
list-style-type: none;
margin: 0;
padding: 0;
text-align: center;
}
ul.img-list li {
display: inline-block;
height: 150px;
margin: 0 1em 1em 0;
position: relative;
width: 150px;
}
span.text-content {
background: rgba(0,0,0,0.5);
color: white;
cursor: pointer;
display: table;
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
opacity: 0;
-webkit-transition: opacity 500ms;
-moz-transition: opacity 500ms;
-o-transition: opacity 500ms;
transition: opacity 500ms;
}
span.text-content span {
display: table-cell;
text-align: center;
vertical-align: middle;
}
ul.img-list li:hover span.text-content {
opacity: 1;
}
<ul class="img-list">
<li>
<a href="#">
<img src="http://placehold.it/150x150">
<span class="text-content"><span>Text</span></span>
</a>
</li>
</ul>
you can use only width to keep image ratio.
you can use display:block for a and img, and use flex to center text.
not too sure about the responsive behavior you look for for, you can use a % width on li or a mix a % width + min-width and max-width.
example with % width set at 50% (and max/min width ) , it can be any other value and units.
ul.img-list {
list-style-type: none;
margin: 0;
padding: 0;
text-align: center;
}
ul.img-list li {
display: inline-block;
vertical-align:top;
margin: 0;
position: relative;
width:50%;
max-width:100vh;
min-width:60vh;
}
ul.img-list li a, ul.img-list li a img {
display:block;
width:100%;
}
span.text-content {
background: rgba(0,0,0,0.5);
color: white;
cursor: pointer;
display:flex;
left: 0;
right:0;
position: absolute;
top: 0;
bottom:0;
opacity: 0;
-webkit-transition: opacity 500ms;
-moz-transition: opacity 500ms;
-o-transition: opacity 500ms;
transition: opacity 500ms;
}
span.text-content span {
margin:auto;
}
ul.img-list li:hover span.text-content {
opacity: 1;
}
* {
margin:0;
padding:0;
}
<ul class="img-list">
<li>
<a href="#">
<img src="http://placehold.it/150x150">
<span class="text-content"><span>Text</span></span>
</a>
</li>
</ul>
You could also do it like this, using pseudo elements to display the overlay content on the image. This method is fully responsive.
.wrapper {
width: 100%;
overflow: auto;
padding: 1%;
box-sizing: border-box;
background: rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
/* Columns floated left */
.col-4 {
width: 33.3%;
float: left;
padding: 1%;
box-sizing: border-box;
height: auto;
overflow: hidden;
}
/* Container to make absolute positioning easier on psuedo element */
.image_container {
position: relative;
overflow: auto;
padding: 0;
margin: 0;
}
.image_container img {
width: 100%;
display: block;
}
/* Structure for ::before element */
#img_1::before,
#img_2::before,
#img_3::before {
background: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0;
right: 0;
height: 100%;
width: 100%;
box-sizing: border-box;
display: block;
opacity: 0;
color: white;
padding: 10px;
transition: 0.5s ease;
}
/* Hover state for container to show ::before on mouseover */
.image_container:hover#img_1::before,
.image_container:hover#img_2::before,
.image_container:hover#img_3::before {
opacity: 1;
cursor: pointer;
}
/* Text for ::before elements */
#img_1::before {
content: 'Image Title 1';
}
#img_2::before {
content: 'Image Title 2';
}
#img_3::before {
content: 'Image Title 3';
}
<div class="wrapper">
<div class="col-4">
<div class="image_container" id="img_1">
<img src="https://images.unsplash.com/reserve/B6PfiQ8QoSzmsZYOCkSB__DSC0530-1.jpg?dpr=1&auto=format&fit=crop&w=1500&h=1004&q=80&cs=tinysrgb&crop=">
</div>
</div>
<div class="col-4">
<div class="image_container" id="img_2">
<img src="https://images.unsplash.com/photo-1418985991508-e47386d96a71?dpr=1&auto=format&fit=crop&w=1500&h=1000&q=80&cs=tinysrgb&crop=">
</div>
</div>
<div class="col-4">
<div class="image_container" id="img_3">
<img src="https://images.unsplash.com/photo-1476362555312-ab9e108a0b7e?dpr=1&auto=format&fit=crop&w=1500&h=1000&q=80&cs=tinysrgb&crop=">
</div>
</div>
</div>
You could also set the images as a background-image for the div which would give you more control over the text in the overlay, if you needed it.

Categories