I'm trying to manipulate what is happening in the fiddle on this forum, but I am having some trouble and I'm not sure where I am going wrong.
I have created my own pen here with a stripped down version of what is on my site.
Essentially what I want to do is whenever you hover over the image or the gray box, the body background color will change. (Ideally a fade in/out type of interaction, but if the fade part can be accomplished via CSS, I can do that).
I tried to changed getElementById (from the example) to getElementsByClassName since I have multiple instances of the class, but that didn't seem to work. I had added back in getElementById and it works where applied (on the image) but I don't think that would be best practice since I will have multiple instances of the class.
Disclaimer: I don't know much about JS, so if there is a better way to do this, I'd be glad to try it out!
I only added the JS in the post here to keep things condensed. HTML and CSS in the codepen.
$(document).ready(function(){
window.onload = function(){
var block1 = document.getElementById('hover-color1');
var body = document.body;
block1.onmouseover = function() {
body.className = 'hover-color1';
}
block1.onmouseout = function() {
body.className = '';
}
};
});
You are looking for a transition on the background color. Add the transition for background-color in your body CSS, then in your hover to change body, set the new background color and the transition will fire and make it animate from color one to the other color.
Javascript:
get the class elements using a node selector to create a nodeList -> querySelectorAll returns a nodeList
iterate over the list to get the event.target
use a mouseover and mouseout event to add/remove the class using classList.add/remove
const block1 = document.querySelectorAll('.hover-color1')
block1.forEach(img => {
img.addEventListener('mouseover', e => {
document.body.classList.add('hover-color1')
})
img.addEventListener('mouseout', e => {
document.body.classList.remove('hover-color1')
})
})
CSS: Add a transition to your CSS for the body on background and then on hover the background change will transition from the background-color set in body to the body.hoverElement background-color.
body {
font-family: 'IBM Plex Sans', sans-serif;
color: #1a1b1f;
font-size: 16px;
line-height: 28px;
font-weight: 400;
-webkit-transition: background-color 1s linear;
-moz-transition: background-color 1s linear;
-o-transition: background-color 1s linear;
-ms-transition: background-color 1s linear;
transition: background-color 1s linear;
}
body.hover-color1 {
background-color: red;
}
$(document).ready(function() {
window.onload = function() {
const block1 = document.querySelectorAll('.hover-color1')
block1.forEach(img => {
img.addEventListener('mouseover', e => {
document.body.classList.add('hover-color1')
})
img.addEventListener('mouseout', e => {
document.body.classList.remove('hover-color1')
})
})
}
})
.w-layout-grid {
display: grid;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
grid-row-gap: 16px;
grid-column-gap: 16px;
}
body {
font-family: 'IBM Plex Sans', sans-serif;
color: #1a1b1f;
font-size: 16px;
line-height: 28px;
font-weight: 400;
-webkit-transition: background-color .5s linear;
-moz-transition: background-color .5s linear;
-o-transition: background-color .5s linear;
-ms-transition: background-color .5s linear;
transition: background-color .5s linear;
}
body.hover-color1 {
background-color: red;
}
.section {
position: relative;
z-index: 10;
width: 100%;
height: auto;
margin-right: 0px;
margin-left: 0px;
padding-right: 30px;
padding-left: 30px;
}
img {
display: block;
max-width: 1200px;
}
.container {
width: 100%;
max-width: 1140px;
margin-right: auto;
margin-left: auto;
}
.paragraph {
margin-bottom: 20px;
border-top: 1px none #525254;
font-family: 'IBM Plex Sans', sans-serif;
color: #525254;
font-size: 16px;
line-height: 1.5em;
letter-spacing: 0.3px;
}
.relative-block {
position: relative;
}
.heading-3.display-mono {
font-family: 'IBM Plex Mono', sans-serif;
color: #1a1b1f;
font-size: 32px;
letter-spacing: 1.1px;
}
.heading-4.display-h6 {
font-family: 'IBM Plex Sans', sans-serif;
font-size: 20px;
line-height: 1.5em;
font-weight: 400;
}
.link {
display: inline-block;
font-family: 'IBM Plex Mono', sans-serif;
line-height: 1.5em;
text-decoration: none;
}
.portfolio-block-left {
position: relative;
max-width: 1440px;
margin: 50px auto;
}
.portfolio-grid-left {
position: relative;
grid-column-gap: 25px;
grid-row-gap: 25px;
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
-ms-grid-rows: auto auto auto auto;
grid-template-rows: auto auto auto auto;
}
.portfolio-image.fade-in-1st {
position: relative;
z-index: 1;
}
.portfolio-title {
position: relative;
z-index: 2;
max-width: 570px;
margin-right: 0px;
margin-left: 0px;
padding: 25px;
background-color: #ccc;
}
.portfolio-block-right {
position: relative;
max-width: 1440px;
margin: 50px auto;
}
.portfolio-grid-right {
position: relative;
grid-column-gap: 25px;
grid-row-gap: 25px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: auto auto auto auto;
}
.max-1440 {
width: 100%;
max-width: 1440px;
margin-right: auto;
margin-left: auto;
}
#w-node-link-block-825bf526 {
grid-column-end: 7;
grid-column-start: 1;
grid-row-end: 4;
grid-row-start: 1;
}
#w-node-eb6e1164-1454-9dc3-9597-76f59d0186bb-825bf526 {
grid-column-end: 8;
grid-column-start: 4;
grid-row-end: 5;
grid-row-start: 3;
align-self: end;
justify-self: end;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="padding-50px section">
<div class="portfolio-block-left">
<div class="w-layout-grid portfolio-grid-left">
<a id="w-node-link-block-825bf526" href="#" class="portfolio-image fade-in-1st w-inline-block">
<img class="hover-color1" src="https://source.unsplash.com/random/1200x400" alt=""></a>
<div id="w-node-eb6e1164-1454-9dc3-9597-76f59d0186bb-825bf526" class="portfolio-title hover-color1">
<h3 class="heading-3 display-mono">Title</h3>
<h4 class="heading-4 display-h6">Secondary Title</h4>View Project
</div>
</div>
</div>
</div>
If you want to attach your mouse events to multiple items you can use querySelectorAll to get references to multiple nodes. They can be ids or classes the selectors are your choice. A data attribute could also be another choice which can be applied to any dom node as well. Regardless of your selectors you need to apply your onmouse events to each node, which is done by looping through the results of querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.
If you want to control a transition without css, you can manipulate a dom nodes style attribute. In this case we apply a transition of 1 second on background and change and the background to either the data attribute if it exists for data-hover-color or else red by default on hover.
const body = document.body;
const domNodes = document.querySelectorAll("[data-hover-changer]");
for (domNode of domNodes) {
domNode.onmouseover = (event) => {
body.style.transition = "background 1s ease";
body.style.background = event.target.dataset.hoverColor || "red";
}
domNode.onmouseout = () => {
body.style.background = "transparent";
}
}
<div id="hoverId" data-hover-changer>Hover to change background to red</div>
<div class="hoverClass" data-hover-changer data-hover-color="yellow">Hover to change background to yellow</div>
<div class="hoverClass" data-hover-changer data-hover-color="green">Hover to change background to green</div>
<div>Hover will not work on me</div>
Related
my Friends I have a problem.i have a project that has 3 buttons in it's header .these buttons change width of main div to my specific width has set in my Java script.i want something like media queries for example change my div color or hide or show something when div width changes. i know I can use Java script to define background color for every width but imagine that i have navbar that has sandwich menu button on mobile.this button can easily hide in an specific width that i have defined on my media queries;but what about hiding this button when my main div width decreases to mobile view width instead of changing browser width?
please excuse me for this long text.
<body>
<header>
<span role="button" class="header-collapse"
><i class="fas fa-angle-up"></i
></span>
<ul class="screens">
<li>
<i class="fas fa-mobile-alt"></i>
</li>
<li>
<i class="fas fa-tablet-alt"></i>
</li>
<li>
<i class="fas fa-desktop"></i>
</li>
</ul>
</header>
<main class="content">
</main>
<footer>
<span>Coded by Mahdi Baghaei</span>
</footer>
<script src="./js/app.js"></script>
</body>
*,
html {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
flex-direction: column;
font-family: "poppins", sans-serif;
}
header {
min-height: 5vh;
position: relative;
background-color: #e4e1fc;
width: 15%;
margin: 0 auto;
transition: all 0.2s ease;
}
.header-collapse {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
top: 100%;
background-color: #e4e1fc;
width: 2rem;
height: 1rem;
display: flex;
justify-content: center;
align-items: center;
color: #2512cc;
cursor: pointer;
transition: background-color 0.3s ease, color 0.2s ease;
}
.header-collapse:hover {
background-color: #a49af6;
color: white;
}
.header-set {
transform: translateY(-100%);
}
.header-collapse-set {
transform: translateX(-50%) rotateZ(-180deg);
}
.screens {
width: 100%;
margin: 0 auto;
display: flex;
list-style: none;
justify-content: space-around;
height: 100%;
align-items: center;
padding: 1rem;
}
.screens li a {
width: 2rem;
height: 2rem;
display: flex;
flex-direction: column;
text-align: center;
justify-content: center;
transition: background-color 0.3s ease, color 0.2s ease;
color: #2512cc;
align-items: center;
}
.screens li a:hover {
background-color: #a49af6;
color: white;
}
.screens li a i {
font-size: 1rem;
}
.content {
width: 100%;
height: 75vh;
transition: all 0.4s ease;
margin: auto;
border: 1px solid white;
}
.content-mobile {
width: 768px;
}
.content-tablet {
width: 1200px;
}
footer {
margin-top: auto;
background-color: #e4e1fc;
min-height: 5vh;
padding: 1rem;
text-align: center;
}
footer span {
font-size: 0.9rem;
}
#media screen and (max-width: 768px) {
.content {
background-color: red;
}
}
#media screen and (min-width: 768px) {
.content {
background-color: green;
}
}
#media screen and (min-width: 1200px) {
.content {
background-color: blue;
}
}
const header = document.querySelector("header");
const headerCollapse = document.querySelector(".header-collapse");
const content = document.querySelector(".content");
const screenSwitch = document.querySelectorAll(".screens li");
headerCollapse.addEventListener("click", headerCollapseF);
function headerCollapseF() {
header.classList.toggle("header-set");
headerCollapse.classList.toggle("header-collapse-set");
}
screenSwitch[0].addEventListener("click", mobileView);
screenSwitch[1].addEventListener("click", tabletView);
screenSwitch[2].addEventListener("click", standardView);
function mobileView() {
content.style.width = "768px";
content.style.border = "1px solid black";
}
function tabletView() {
content.style.width = "1200px";
content.style.border = "1px solid black";
}
function standardView() {
content.style.width = "100%";
content.style.border = "1px solid white";
}
I have solved my problem by using iframe html tag
thanks you all.
Example Output
JSX code
<div>
<h3>Person</h3>
{isOnline &&<p>online</p>}
</div>
Need CSS for this Example Output
Css: i have a div with display flex which makes img and the span align horizontally, inside my span i have a h1 and a p tag.
for the h1 i have set some css properties and a transformY(10px) that means i am moving it up 10px from its original position.and a transition with time and animation type.
for the p i have also set some properties and a opacityof 0;
then i am just saying if my wrapper has a class of online in it then do this to h1 and p.
i am toggling that online class with a button for demo purpose. but in real life it can be with anything.
let wrapper = document.querySelector(".wrapper");
let btn = document.querySelector(".btn");
btn.addEventListener("click",()=>{
wrapper.classList.toggle("online")
})
.wrapper {
width: 510px;
height: 130px;
background-color: #017d68;
display: flex;
align-items: center;
padding: 10px;
gap: 30px;
}
img {
height: 120px;
border-radius: 100%
}
p {
font-size: 20px;
color: white;
opacity: 0;
transition: all 0.25s ease-in-out;
}
h1 {
font-family: Arial, Helvetica, sans-serif;
color: white;
transform: translateY(10px);
transition: all 0.25s ease-in-out;
}
.wrapper.online h1{
transform: translateY(-10px);
}
.wrapper.online p {
opacity: 1;
}
<div class="wrapper">
<img src="https://images.unsplash.com/photo-1493106819501-66d381c466f1?ixlib=rb- 1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80"
alt="">
<span>
<h1>Person</h1>
<p>online</p>
</span>
</div>
<button class="btn">Change Status</button>
I'm trying to make this news item component interface for a blog. Each item shows a story image and some of the text of the article. Rolling over the news item should "scrunch up" the image and reveal more of the text of the article. I can't see why my animation does not hold when you rollover the item, and then it resets completely before performing the "unscrunching."
There are keyframe animations that attach and detach to the item:
#keyframes scrunch {
from {
height: 50%;
}
to {
height: 10%;
}
}
#keyframes unscrunch {
from {
height: 10%;
}
to {
height: 50%;
}
}
.scrunch {
animation: scrunch 1s;
}
.unscrunch {
animation: unscrunch 1s;
}
Then I'm just adding and removing those classes from the news item class list:
const scrunchyBox = document.getElementById('scrunchyBox1');
const children = scrunchyBox.childNodes;
console.dir(children);
const scrunchyBoxHead = children[1];
scrunchyBox.addEventListener('pointerover', (event) => {
scrunchyBoxHead.classList.remove('unscrunch');
scrunchyBoxHead.classList.add('scrunch');
});
scrunchyBox.addEventListener('pointerout', (event) => {
scrunchyBoxHead.classList.remove('scrunch');
scrunchyBoxHead.classList.add('unscrunch');
});
Seems basic, but whatever I'm doing looks gross. Everything I've done is over at my Codepen.
You can use the transition property with the :hover pseudo-class. This will be the same that you have tryed to do with javascript.
To achieve this, just add few lines to your css file.
/* new block */
.scrunchyBox:hover .sectionHead {
height: 10%;
}
/* new block */
.scrunchyBox:hover .datedot {
transform: scale(0.45) translate(60px, -72px);
}
.scrunchyBox > .sectionHead {
transition: all 0.5s ease-in-out; /* new line */
}
.datedot {
transition: all 0.5s ease-in-out; /* new line */
}
body {
background-color: #ccc;
font-size: 18px;
}
.scrunchyBox {
color: #333;
position: relative;
background-color: #fff;
width: 400px;
height: 400px;
margin: 0 auto;
padding: 20px;
overflow: hidden;
filter: drop-shadow(4px 4px 4px #333);
}
/* new block */
.scrunchyBox:hover .sectionHead {
height: 10%;
}
/* new block */
.scrunchyBox:hover .datedot {
transform: scale(0.45) translate(60px, -72px);
}
.scrunchyBox > .sectionHead {
width: 400px;
height: 250px;
background-color: #3ab7f4;
padding: 0;
margin: 0 auto;
transition: all 0.5s ease-in-out; /* new line */
}
.datedot {
position: absolute;
top: 30px;
right: 30px;
background-color: rgba(0, 0, 0, 0.3);
padding: 12px;
border-radius: 60px;
width: 60px;
height: 60px;
transition: all 0.5s ease-in-out; /* new line */
}
.datedot > span {
font-family: 'Trebuchet MS', sans-serif;
color: rgba(255, 255, 255, 1);
text-align: center;
display: block;
margin: 0;
}
.datedot > span.day {
font-size: 2.2em;
font-weight: bold;
line-height: 0.8em;
padding: 0;
}
.datedot > span.month {
font-size: 1.3em;
font-weight: normal;
text-transform: uppercase;
padding: 0;
}
.scrunchyBox > h2 {
font-family: 'Trebuchet MS', sans-serif;
font-size: 1.2em;
line-height: 1em;
padding: 0;
}
.scrunchyBox > p {
font-family: 'Georgia', serif;
font-size: 1.4em;
}
<div id="scrunchyBox1" class="scrunchyBox">
<div class="sectionHead">
<div class="datedot">
<span class="day">30</span>
<span class="month">Oct</span>
</div>
</div>
<h2>A Headline for the Scrunchy Box</h2>
<p>
This is some text that would normally be some text that the reader would want to see more of. It gets cut off here by other elements, but then other elements "scrunch" in order to reveal more of the text for a preview.
</p>
</div>
You can retain the animation in its final state using animation-fill-mode: forwards; as described in answer to this question: Maintaining the final state at end of a CSS3 animation
It will still look janky if you remove pointer from the box mid-animation. I am not sure why you don't want to simply use CSS :hover with transition.
I'm trying to create a "bubble" which gets bigger in order to change its parent color with a nice animation. I like my approach, but I only need to put it inside the parent div.
This is what I have:
HTML
<html>
<body>
<div class="nav-menu" style="top: -64px;">
<div class="test"></div>
<div class="brand" onclick="test();">
<h1>App</h1>
</div>
<ul class="menu-list">
<li class="menu-item">Item</li>
</ul>
</div>
</body>
</html>
CSS
#import url('https://fonts.googleapis.com/css2?family=Satisfy&display=swap');
* {
margin: 0;
padding: 0;
}
.nav-menu {
z-index: 1000;
padding: 0 16px;
display: flex;
justify-content: space-between;
background-color: #B67171;
color: white;
position: fixed;
width: 100%;
transition: background-color .5s, top .2s;
}
.test {
background-color: blue;
position: absolute;
border-radius: 50%;
z-index: -1;
width: 32px;
height: 32px;
left: 50%;
top: 50%;
transform: scale(0) translate(-50%, -50%);
transform-origin: top left;
transition: transform .25s;
}
.nav-menu .brand h1 {
margin: 0;
padding: 0;
line-height: 64px;
font-family: 'Satisfy', cursive;
}
.nav-menu .menu-list {
list-style: none;
margin: 0;
}
.nav-menu .menu-list a {
display: inline-block;
margin: 0;
padding: 0 16px;
line-height: 64px;
font-size: 21px;
vertical-align: middle;
transition: background-color .2s;
color: white;
text-decoration: none;
}
.nav-menu .menu-list a:hover {
background-color: #D8C292;
}
(And a .js just for testing)
let navMenu = document.getElementsByClassName("nav-menu")[0];
window.addEventListener('load', function (e) { navMenu.style.top = "0"; });
var showing = false;
function test () {
document.getElementsByClassName("test")[0].style = "transform: scale(" + (showing ? 0 : 4) + ") translate(-50%, -50%);";
showing = !showing;
}
Here you have a demo in which you can press the "App" text and it would scale the "bubble" just a little bit. I want to remove the following stuff:
Can anybody give me a hint? However if you know any better solution for this "feature", I will appreciate it.
Thank you in advance!
Adding overflow:hidden property to your navigation div would work. Try this code.
.nav-menu {
z-index: 1000;
padding: 0 16px;
display: flex;
justify-content: space-between;
background-color: #B67171;
color: white;
position: fixed;
width: 100%;
transition: background-color .5s, top .2s;
overflow: hidden;
}
Add to .navmenu property overflow
DOC: overflow
nav-menu {
...
overflow: hidden;
}
Simply add overflow: hidden; to your div with class nav-menu.
Here is your edited example: https://jsfiddle.net/4r1n2cux/2/
use overflow: hidden; in style of first <div>
Please take a look at the below example. I'm learning css grids. The whole purpose is to keep things simple and to not need to specify distinct layout details on the child elements unnecessarily, so solutions should conform to this pattern.
Given the following:
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
}
.one {
background: red
}
.two {
background: green
}
.three {
background: blue
}
.selected {
width: 150%;
height: 150%;
z-index: 2;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>
https://jsfiddle.net/robbie_at_harvard/a3ouq711/1/
Please adjust to cause the areas two, three and four to expand towards the middle instead of always from the top-left corner? Again, preferably with generic rules rather than ones specific to the div.class specifications.
Second question, if I wanted instead a 4x4 layout of 2x2 child elements, where clicking on one element expanded it to 3x3 and contracted the others to 1x2, 2x1, and 1x1 in the opposite corner, what is necessary to produce this solution?
You could use transform:scale(1.5) and position it with transform-origin.
It would require specific CSS rules depending on the grid (i use :nth-child to target each element)
For 2x2 use
main div:nth-child(1){transform-origin: top left;}
main div:nth-child(2){transform-origin: top right;}
main div:nth-child(3){transform-origin: bottom left;}
main div:nth-child(4){transform-origin: bottom right;}
.selected {
transform:scale(1.5);
z-index: 2;
}
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
}
.one {
background: red
}
.two {
background: green
}
.three {
background: blue
}
main div:nth-child(1) {
transform-origin: top left;
}
main div:nth-child(2) {
transform-origin: top right;
}
main div:nth-child(3) {
transform-origin: bottom left;
}
main div:nth-child(4) {
transform-origin: bottom right;
}
.selected {
transform: scale(1.5);
z-index: 2;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>
I think it's difficult to have a general solution since the 4 blocks need to move in different ways. By the way here a solution that involve few CSS changes.
I know you want a generic one but i think in all the cases you will have some specificities (like the color and the content)
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
position:relative;
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
transition:0.5s;
}
.one {
background: red;
}
.two {
background: green;
right:25%;
}
.three {
background: blue;
bottom:25%;
}
.four {
bottom:25%;
right:25%;
}
.selected {
position:relative;
width:150%;
height:150%;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>