SVG Drawing Function Is Messing Up - javascript
So, I'm trying to do this animation where I can carousel through the content on this page in a slideshow/multi-step form kind of manner. That's working pretty good. However, I have this SVG drawing function that I want to call for each specific "slide", when the transfer function has happened. So transfer forward to section or backwards to section has happened, the specific SVG for that section is drawn.
But my svg function is messing up - maybe all of it is?
I don't know. I'm a newbie, so please be nice to me about my code - even if it's not great.
Also, I included a big chunk of code so thank you to whoever reads through this. Love you in advance :).
const multiStepForm = document.querySelector("[data-multi-step]");
const formSteps = [...multiStepForm.querySelectorAll("[data-step]")];
let currentStep = formSteps.findIndex(step => {
return step.classList.contains('active')
});
if(currentStep < 0) {
currentStep = 0;
showCurrentStep();
};
multiStepForm.addEventListener('click', e => {
let incrementor
if (e.target.matches("[data-next]")) {
incrementor = 1
} else if (e.target.matches("[data-previous]")){
incrementor = -1
}
if(incrementor == null) return
if(e.target.matches("[data-next]")){
currentStep += incrementor
showCurrentStep()
} else if (e.target.matches("[data-previous]")) {
currentStep += incrementor
showCurrentStep()
}
});
formSteps.forEach(step => {
step.addEventListener('animationend', e => {
formSteps[currentStep].classList.remove('hide')
e.target.classList.toggle('hide', !e.target.classList.contains('active'))
})
})
function writeSignature(totalDur, paths){
// get all SVG elements - lines and dots
const linePaths = document.querySelectorAll(paths);
// reset the animation
linePaths.forEach((linePath) => {
linePath.classList.remove('animated')
})
// escape if no element is found
if(!linePaths.length){
return false;
};
// set animation duration to default if not set
const totalDuration = totalDur || 7;
linePaths.forEach((linePath) => {
const pathElem = linePath;
// get current path length
const pathLength = linePath.getTotalLength();
// set animation duration and delay
pathElem.style.animationDuration = `${totalDuration}s`;
// set dash array and offset to path length - to hide the path
linePath.setAttribute('stroke-dasharray', pathLength);
linePath.setAttribute('stroke-dashoffset', pathLength);
});
// set 'animated' class to body which will start the animation
linePaths.forEach((linePath) => {
linePath.classList.add('animated')
});
return true;
};
function showCurrentStep() {
formSteps.forEach((step,index) => {
step.classList.toggle('active', index === currentStep)
if(step.classList.contains('systems')){
writeSignature(2.5, '.system-path');
} else if(step.classList.contains('socials')){
writeSignature(2.5, '.social-path');
} else if(step.classList.contains('web')){
writeSignature(2.5, '.web-path');
}
});
};
.main-content {
width: 75vw;
height: 75vh;
margin: auto;
position: relative;
}
.main-content-svc{
background:#3244AB;
}
.steps-container {
width: 100%;
height: 100%;
}
.multi-step-container {
padding: 0;
margin: 0;
overflow: hidden;
position: relative;
height: 100%;
width: 100%;
}
.step {
position: relative;
height: 100%;
width: 100%;
list-style: none;
cursor: pointer;
animation: fade 250ms ease-in-out forwards;
}
.systems-info, .social-info, .web-info{
width: 60%;
display: grid;
grid-template-columns: auto auto auto auto;
gap: 40px ;
padding: 25px;
}
.social-info h2, .social-intro,
.systems-info h2, .systems-intro,
.web-info h2, .web-intro{
text-align: center;
}
.social-paras, .systems-paras, .web-paras {
display: inline-flex;
}
.social-info h2, .systems-info h2, .web-info h2 {
grid-column-start: 1;
grid-column-end: 5;
}
.social-intro, .systems-intro, .web-intro {
grid-column-start: 1;
grid-column-end: 5;
}
.social-para1, .social-para3,
.systems-para1, .systems-para3,
.web-para1, .web-para3 {
grid-column-start: 1;
grid-column-end: 3;
}
.social-para2, .social-para4,
.systems-para2, .systems-para4,
.web-para2, .web-para4 {
grid-column-start: 3;
grid-column-end: 5;
}
#system-svgs {
width: 500px;
position: absolute;
right: -10%;
top: 10%;
}
#web-svgs {
width: 500px;
position: absolute;
right: 0;
top: 5%;
}
.twitter-lines {
position: absolute;
right: 10%;
bottom: 15%;
}
.facebook-lines {
position: absolute;
right: 20%;
top: 12%;
}
.pinterest-lines {
position: absolute;
right: 5%;
top: 5%;
}
#services-pg path {
animation-timing-function: linear;
animation-fill-mode: forwards;
}
.animated {
animation-name: writeSVG;
}
.buttons {
width: 100%;
text-align: center;
position: absolute;
left: 0;
bottom: 2%;
display: inline-block;
margin: 5px;
}
.buttons button {
background-color: transparent;
border: none;
}
.step.active {
animation: slide 250ms 250ms ease-in-out both;
}
.hide {
display: none;
}
#keyframes writeSVG {
100% {
stroke-dashoffset: 0;
}
}
#keyframes slide {
0% {
transform: translateX(200%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
#keyframes fade {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(0.75);
opacity: 0;
}
100% {
transform: scale(0);
opacity: 0;
}
}
<main id="svc-container" class="main-content main-content-svc">
<div class="steps-container">
<ul data-multi-step class="multi-step-container">
<li id="systems" class="active step systems" data-step>
<div class="systems-info">
<h2>Systems</h2>
<p class="systems-intro">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur iure qui dolore velit nihil excepturi sequi cumque. Asperiores inventore, provident libero.</p>
<div class="systems-paras systems-para1">
<h4>1)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate.</p>
</div>
<div class="systems-paras systems-para2">
<h4>2)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur.</p>
</div>
<div class="systems-paras systems-para3">
<h4>3)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
<div class="systems-paras systems-para4">
<h4>4)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
</div>
<div id="system-svgs">
<svg
class="gears"
version="1.1"
viewBox="10 30 40 65"
height="500px"
width="500px">
<g>
<path
class="system-path"
d="m 13.284612,59.22312 c -3.769554,0.0069 -5.504936,2.172975 -5.822185,4.820917 -0.270219,2.530855 1.764121,5.724608 5.043422,5.748017 8.288379,0.261994 7.743937,-10.409386 0.778763,-10.568934 z m 0.112676,17.376856 -3.689262,-0.322894 0.35566,-3.648968 C 9.511117,72.492687 8.940024,72.335648 7.806573,71.522526 L 4.887021,73.848285 2.502685,71.16152 5.279688,68.949221 C 4.683138,68.134826 4.413308,67.451118 4.309992,66.834016 L 0.325907,66.958484 0.203642,63.450079 4.050129,63.32984 c -0.03987,-0.562853 0.146358,-1.261368 0.600855,-2.120843 l -3.166947,-2.110354 2.131431,-2.8713 3.115091,2.075859 c 0.83433,-0.956181 1.451323,-1.151682 2.095643,-1.442827 l -1.114617,-3.762509 3.567131,-0.948651 1.109063,3.743719 c 0.639522,-0.02774 0.890155,-0.196898 2.540998,0.143113 l 1.693704,-3.680101 3.39612,1.403109 -1.693669,3.680101 c 0.893449,0.59492 1.443027,1.189839 1.946424,1.784759 l 3.561731,-1.514035 1.516606,3.202754 -3.458795,1.470261 c 0.22664,0.730152 0.433222,1.465318 0.271919,2.292456 l 3.703698,0.947806 -0.96611,3.389011 -3.569731,-0.913651 c -0.332382,0.786544 -0.690051,1.573088 -1.700462,2.359632 l 2.207297,3.09999 -3.071288,1.963345 -2.190881,-3.076837 c -1.230003,0.498413 -2.097299,0.634118 -2.835485,0.640714 z"
style="fill:none;stroke:#4cf5e1;stroke-width:0.5;opacity:1;"/>
<path
class="system-path"
d="m 14.354871,39.21616 c -2.709478,-1.447135 -4.730714,-0.543226 -5.906005,1.256879 -1.099582,1.733252 -0.781496,4.835506 1.565052,6.115827 5.858287,3.383243 9.285683,-4.573592 4.340953,-7.372706 z M 8.218108,51.874629 5.68432,50.218954 7.245368,47.706922 C 6.897007,47.395744 6.543091,47.061718 6.020087,46.034763 L 3.091316,46.598454 2.340444,43.729393 5.126248,43.193156 c -0.136984,-0.821037 -0.08612,-1.42134 0.0605,-1.909138 l -2.90558,-1.44447 1.167551,-2.594098 2.805255,1.394544 c 0.172752,-0.42398 0.556427,-0.859337 1.190352,-1.308191 L 5.925197,34.579705 8.483205,33.316351 9.977438,36.02343 c 0.941282,-0.372739 1.454309,-0.276974 2.021181,-0.240118 l 0.54585,-3.160864 2.901063,0.685525 -0.543117,3.145083 c 0.469174,0.226236 0.709689,0.199988 1.773531,1.082795 l 2.533069,-2.019146 1.936765,2.326942 -2.53305,2.019166 c 0.428738,0.77609 0.610526,1.419702 0.759153,2.045525 l 3.099486,0.272993 -0.05688,2.909364 -3.009904,-0.265115 c -0.0985,0.617378 -0.213207,1.230669 -0.625,1.769007 l 2.320552,2.114901 -1.906416,2.088132 -2.236566,-2.038498 c -0.520128,0.442957 -1.058417,0.876176 -2.065445,1.05793 l 0.47588,3.100841 -2.908057,0.242134 -0.472377,-3.077709 C 10.925532,49.970285 10.254154,49.734696 9.721688,49.455103 Z"
style="fill:none;stroke:#4cf5e1;stroke-width:0.5;opacity:1;"/>
<path
class="system-path"
d="m 28.625511,48.835168 c -2.229634,-0.294553 -3.430783,0.847615 -3.832237,2.386691 -0.364191,1.473635 0.580861,3.52139 2.518148,3.794952 4.880085,0.81124 5.419984,-5.535723 1.314089,-6.181643 z m -1.336771,10.27385 -2.155528,-0.482945 0.505015,-2.127362 C 25.322409,56.37495 24.997382,56.236945 24.392798,55.666839 l -1.914281,1.142642 -1.192961,-1.775985 1.820822,-1.086908 c -0.286991,-0.528331 -0.391333,-0.953587 -0.402589,-1.326306 l -2.365999,-0.242042 0.211053,-2.082183 2.284289,0.233628 c 0.02191,-0.335646 0.188419,-0.733527 0.526596,-1.205243 l -1.702303,-1.497472 1.49229,-1.527327 1.674426,1.472987 c 0.570595,-0.498756 0.951237,-0.565376 1.355762,-0.68633 l -0.355249,-2.310886 2.186002,-0.27786 0.353481,2.299348 c 0.380419,0.0342 0.542286,-0.0458 1.491032,0.285806 l 1.298769,-2.039778 1.894943,1.097839 -1.298749,2.039776 c 0.480285,0.422199 0.757224,0.817161 1.006855,1.208465 l 2.228469,-0.612273 0.638167,2.012064 -2.164064,0.594569 c 0.07505,0.449269 0.137833,0.899911 -0.02434,1.375747 l 2.113596,0.853238 -0.845006,1.925453 -2.037133,-0.822454 c -0.260075,0.438303 -0.535101,0.874607 -1.19612,1.259208 l 1.054898,2.006066 -1.974738,0.916536 -1.047062,-1.991089 c -0.767602,0.197003 -1.291427,0.208474 -1.728479,0.153902 z"
style="fill:none;stroke:#4cf5e1;stroke-width:0.5;opacity:1;"/>
</g>
</svg>
</div>
<div class="buttons">
<button type="button" data-next>Socials →</button>
</div>
</li>
<li id="socials" class="step socials" data-step>
<div class="social-info">
<h2>Socials</h2>
<p class="social-intro">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur iure qui dolore velit nihil excepturi sequi cumque. Asperiores inventore, provident libero.</p>
<div class="social-paras social-para1">
<h4>1)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate.</p>
</div>
<div class="social-paras social-para2">
<h4>2)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur.</p>
</div>
<div class="social-paras social-para3">
<h4>3)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
<div class="social-paras social-para4">
<h4>4)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
</div>
<div id="social-svgs">
<svg
class="twitter-lines"
version="1.1"
viewBox="850 -750 850 850"
height="250px"
width="250px">
<g>
<path
class="social-path"
d="M 1371.638,73.267145 C 1282.6632,22.881521 1106.9129,2.561158 970.86717,92.585006 c 77.31223,-9.378131 150.07103,0.994385 212.10653,57.880064 -111.4902,15.3279 -124.9095,72.0454 -138.2829,97.77243 23.7585,-0.63766 47.5168,-1.70582 71.2752,1.66802 -117.79397,38.56527 -117.01177,140.09919 -117.01177,140.09919 20.65097,-7.19842 40.39617,-16.36068 64.68037,-15.67906 -74.62377,63.10602 -75.21977,129.29951 -50.7356,196.53897 67.6896,-77.57075 148.9319,-143.78545 300.052,-151.44828 -24.0681,68.11848 91.7053,264.05661 242.5268,131.98727 25.9132,-7.82476 55.0522,12.33458 84.7542,37.37698 -7.0544,-30.76945 -6.1736,-62.11256 -68.4795,-88.88787 23.0316,2.70904 34.8831,-9.73587 86.3971,31.57969 -4.5985,-20.69531 -9.83,-49.22123 -56.3749,-69.87587 C 1603.3326,234.22266 1448.2495,107.3751 1371.638,73.267145 Z"
style="fill:none;stroke:#4cf5e1;stroke-width:8;opacity:1;"
transform="scale(1,-1)"/>
</g>
</svg>
<svg
class="facebook-lines"
version="1.1"
viewBox="950 -400 350 350"
height="250px"
width="250px">
<g>
<path
class="social-path"
d="m 1185.4417,352.252 c -44.0308,-2.93942 -101.1573,17.27671 -93.0549,-92.7576 h -39.5234 v -45.95715 h 39.5234 v -111.4893 l 45.0653,0.1032 1.0479,111.3861 h 43.6481 V 259.4944 H 1138.5 c -1.2058,61.05759 4.347,49.63388 46.9417,50.07997 V 352.252"
style="fill:none;stroke:#4cf5e1;stroke-width:3.5;opacity:1;"
transform="scale(1,-1)"/>
</g>
</svg>
<svg
class="pinterest-lines"
version="1.1"
viewBox="1000 -475 450 450"
height="250px"
width="250px">
<g>
<path
class="social-path"
d="m 1163.8809,110.83362 c -8.5615,-4.76259 -9.0546,17.97745 -12.8107,29.59485 1.5189,40.39107 19.7671,73.33812 24.3142,116.2338 -26.2638,59.88131 14.5762,86.97703 43.8842,84.21015 34.0357,-15.71279 1.2869,-68.27225 -5.9303,-106.74525 -7.607,-27.66551 37.4846,-41.47442 59.3029,-26.68637 73.4249,50.7141 26.9472,170.56116 -34.9887,166.64129 -76.3165,3.81259 -86.9575,-55.15298 -93.1057,-77.09384 -0.5338,-43.63739 18.4588,-31.04584 16.6049,-69.38443 -20.558,-4.54562 -40.4012,39.87221 -36.7679,74.1287 15.8015,101.49563 89.5039,98.80371 95.4778,100.81501 145.8932,0.59738 173.0445,-185.86557 51.5935,-224.75821 -35.3925,-6.01894 -54.291,9.53415 -68.0339,23.0914 -6.4287,-43.5186 -25.9041,-82.88567 -39.5403,-90.0471 z"
style="fill:none;stroke:#4cf5e1;stroke-width:4;opacity:1;"
transform="scale(1,-1)"/>
</g>
</svg>
</div>
<div class="buttons">
<button type="button" data-previous>← Systems </button>
<button type="button" data-next>Web →</button>
</div>
</li>
<li id="web" class="step web" data-step>
<div class="web-info">
<h2>Web</h2>
<p class="web-intro">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur iure qui dolore velit nihil excepturi sequi cumque. Asperiores inventore, provident libero.</p>
<div class="web-paras web-para1">
<h4>1)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate.</p>
</div>
<div class="web-paras web-para2">
<h4>2)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique, maxime quos voluptate aspernatur.</p>
</div>
<div class="web-paras web-para3">
<h4>3)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
<div class="web-paras web-para4">
<h4>4)</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe, quis. Officia nam dignissimos quae, provident architecto consequatur similique.</p>
</div>
</div>
<div id="web-svgs">
<svg
class="web-build"
version="1.1"
viewBox="-15 -25 175 175"
height="500px"
width="500px">
<g>
<path
class="web-path"
d="M 60.647144,112.82787 C 65.305556,104.58148 45.282102,73.931698 35.075129,51.835166 l -8.46641,3.628462 c 8.757646,15.108739 29.083175,62.837452 34.038425,57.364242 z"
style="fill:none;stroke:#4cf5e1;stroke-width:1;opacity:1;"/>
<path
class="web-path"
d="M 25.053664,53.563005 16.068902,29.546045 C 0.56706111,31.526934 9.1250601,19.272702 0,0 11.54679,19.242498 26.096809,12.560767 19.697363,27.299854 L 33.692858,49.76176 Z"
style="fill:none;stroke:#4cf5e1;stroke-width:1;opacity:1;"/>
<path
class="web-path"
d="M 73.433152,29.546045 V 42.159269 L 62.720551,46.997217 73.77872,52.180734 73.605936,65.485093 44.405459,47.342785 Z"
style="fill:none;stroke:#4cf5e1;stroke-width:1;opacity:1;"/>
<path
class="web-path"
d="M 102.63363,8.1208427 112.65509,8.2936266 86.564728,84.664105 H 75.852127 Z"
style="fill:none;stroke:#4cf5e1;stroke-width:1;opacity:1;"/>
<path
class="web-path"
d="M 114.21015,29.546045 141.68279,46.65165 113.51901,65.657877 V 52.00795 l 11.23096,-5.529084 -10.88539,-5.529085 z"
style="fill:none;stroke:#4cf5e1;stroke-width:1;opacity:1;"/>
</g>
</svg>
</div>
<div class="buttons">
<button type="button" data-previous>← Socials</button>
</div>
</li>
</ul>
</div>
</main>
Related
Find element that's on the middle of the visible screen (viewport) to target another element
What I am aiming to achieve is something that looks like this. you can see it in action on this URL, if you scroll a bit. I was thinking at first to try using inViewport, and every time a heading or a paragraph is in viewport to show one image and hide the previous. but my problem is that the elements are in viewport in conjunction This is the initial code I was using: $.fn.isInViewport = function () { let elementTop = $(this).offset().top; let elementBottom = elementTop + $(this).outerHeight(); let viewportTop = $(window).scrollTop(); let viewportBottom = viewportTop + window.innerHeight; // <-- here return elementBottom > viewportTop && elementTop < viewportBottom; }; $(window).scroll(function () { if ($('.heading1 ').isInViewport()) { // Use .blogcard instead of this $('.img1').addClass('show'); } else { // Remove class $('.img1').removeClass('show'); } if ($('.heading2 ').isInViewport()) { // Use .blogcard instead of this $('.img2').addClass('show'); } else { // Remove class $('.img2').removeClass('show'); } }); I have found this answer but have no idea on how can I use is to my benefits. I have also stumbled upon this solution, which looks even smarter, but the code adds the classes to the selector in viewport and not to a different element. This is the code applied there: ar getElementsInArea = (function(docElm){ var viewportHeight = docElm.clientHeight; return function(e, opts){ var found = [], i; if( e && e.type == 'resize' ) viewportHeight = docElm.clientHeight; for( i = opts.elements.length; i--; ){ var elm = opts.elements[i], pos = elm.getBoundingClientRect(), topPerc = pos.top / viewportHeight * 100, bottomPerc = pos.bottom / viewportHeight * 100, middle = (topPerc + bottomPerc)/2, inViewport = middle > opts.zone[1] && middle < (100-opts.zone[1]); elm.classList.toggle(opts.markedClass, inViewport); if( inViewport ) found.push(elm); } }; })(document.documentElement); //////////////////////////////////// // How to use: window.addEventListener('scroll', f) window.addEventListener('resize', f) function f(e){ getElementsInArea(e, { elements : document.querySelectorAll('div'), markedClass : 'highlight--1', zone : [20, 20] // percentage distance from top & bottom }); getElementsInArea(e, { elements : document.querySelectorAll('div'), markedClass : 'highlight--2', zone : [40, 40] // percentage distance from top & bottom }); } Would love all the help I could get. Cheers
Using the IntersectionObserver API It should be quite simple by using the IntersectionObserver API to watch for your elements intersecting the viewport, or any other (Options root) ancestor. To detect an element reaches the viewport vertical center can be done by passing the Option rootMargin where the bottom and top values are set at -50%, with an Option threshold set to 0 (as soon as one pixel enters that intersecting area) // Utility functions: const EL = (sel, par) => (par || document).querySelector(sel); const ELS = (sel, par) => (par || document).querySelectorAll(sel); // App: const ELS_pictures = ELS(".picture"); const switchPicture = (EL_entry) => { const EL_picTarg = EL(EL_entry.dataset.reveal); ELS_pictures.forEach(EL_pic => EL_pic.classList.toggle("is-active", EL_pic === EL_picTarg)); }; // In Viewport const inViewport = (entries, observer) => entries.forEach(entry => entry.isIntersecting && switchPicture(entry.target)); // Assign observer to all Elements with data-reveal attribute (Articles) ELS("[data-reveal]").forEach(el => { const observer = new IntersectionObserver(inViewport, { // root: (by default is Document), rootMargin: "-50% 0px -50% 0px", // set the root intersecting area as a tiny line in the vertical center threshold: 0, // 0 = as soon as 1px intersects }); observer.observe(el); }); /* QuickReset */ * { margin: 0; box-sizing: border-box; } body { font: 18px/1.5 sans-serif; } .stickers { display: grid; grid-template-columns: 2fr 3fr; max-width: 1000px; margin: 0 auto; } /* Article Component */ .articles { display: flex; flex-direction: column; } .article { margin: 100px 0; padding: 30px; } .pictures { position: sticky; display: flex; top: 0px; right: 0; height: 100vh; background: #444; } .picture { position: absolute; height: 100%; width: 100%; object-fit: cover; margin: auto; transition: 0.3s opacity, 0.5s transform; opacity: 0; transform: scale(0.8); } .picture.is-active { opacity: 1; transform: scale(1); } <p style="height: 80vh;">Scroll down...</p> <div class="stickers"> <div class="articles"> <div class="article" data-reveal="#picture_1"> <h1>Many cats</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio laudantium perferendis eius iusto vitae eaque, eligendi ullam, rerum maiores, totam velit! Debitis repudiandae aliquam placeat, minus. Facere nihil aspernatur nam!</p> </div> <div class="article" data-reveal="#picture_2"> <h1>Little cat</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p> </div> <div class="article" data-reveal="#picture_3"> <h1>Snowcat</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p> </div> <div class="article" data-reveal="#picture_4"> <h1>Cat</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut recusandae doloribus laboriosam, quasi aspernatur modi illum voluptate dicta alias optio, omnis qui deserunt. Quisquam, beatae dolores cum nostrum sint minima!</p> </div> </div> <div class="pictures"> <img class="picture is-active" id="picture_1" src="https://placekitten.com/380/300" alt="Catz!"> <img class="picture" id="picture_2" src="https://placekitten.com/460/400" alt="Catz!"> <img class="picture" id="picture_3" src="https://placekitten.com/400/450" alt="Catz!"> <img class="picture" id="picture_4" src="https://placekitten.com/500/450" alt="Catz!"> </div> </div> <p style="height: 180vh;">Etc...</p> Use data-* Attribute on your articles Elements where the value should match the selector of the related picture. Toggle a class i.e: .is-active using classList that will determine the active styles for the matching picture Element To make the fixed effect use position: sticky on your pictures parent element.
How to set collapse on all other divs when one div is open?
I have seen many questions but none are similar to my case. I have bootstrap collapse and show for a few div contents. The div content shows when title is clicked. I want to close all other div contents when I click another content's title. The color of the title div is gray and should change to white when its content shows. Once the content is collapsed, title div color should back to gray. Here's my code: function collapse (e, id, collapasibleName) { var toggleColor = document.getElementById(id); var collapsibles = document.getElementById(collapasibleName); if(collapsibles.className == 'home__questions-content collapse' || collapsibles.className == 'home__questions-content collapsed') { alert("Sdfsdfdsf") toggleColor.classList.remove('home__questions-title-show'); } if(collapsibles.className == 'home__questions-content collapse show') { alert("in show") toggleColor.classList.add('home__questions-title-show'); } } .home__more-questions-content { padding-right: 40px; padding-left:40px; padding-bottom: 20px; background-color: $white-color; position:relative; max-width: 1080px; margin: auto; } .home__questions-content-tile { margin-bottom: 10px; border:1px solid #eee; } .home__questions-content-title { padding:20px; background-color: #000 cursor: pointer; } .home__questions-content { padding-top: 0; padding-right:20px; padding-left:20px; padding-bottom:20px; } .home__questions-title-show { background-color: #fff; } .collapse { display:none; } .collapse.show { display: block; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } <div class="home__more-questions-content" id="accordion"> <div class="home__questions-content-tile"> <div class="home__questions-content-title" data-toggle="collapse" data-target="#collapsible-one" data-parent="#accordion" id="collapse-one" onclick="collapse(event, this.id,'collapsible-one');"> <h2> // title 1 here </h2> </div> <div class="home__questions-content collapse" id="collapsible-one"> //title 1's content here </div> </div> <div class="home__questions-content-tile"> <div class="home__questions-content-title" data-toggle="collapse" data-target="#collapsible-two" data-parent="#accordion" id="collapse-two" onclick="collapse(event, this.id,'collapsible-two');"> <h2> //title 2 </h2> </div> <div class="home__questions-content collapse" id="collapsible-two"> //title 2's content here </div> </div> <div class="home__questions-content-tile"> <div class="home__questions-content-title" data-toggle="collapse" data-target="#collapsible-three" data-parent="#accordion" id="collapse-three" onclick="collapse(event, this.id, 'collapsible-three');"> <h2> //title 3 </h2> </div> <div class="home__questions-content collapse" id="collapsible-three"> // title 3's content here </div> </div> </div>
Here is the code, explanation is in the comment of the question. Add new code if (e.target.parentNode.classList.contains('active')) { e.target.parentNode.classList.remove('active') return } If current block is opened, then close it and return from further processing. const container = document.querySelector('.container') container.addEventListener('click', e => { if (e.target.parentNode.classList.contains('active')) { e.target.parentNode.classList.remove('active') return } const collapsable = document.querySelectorAll('.item') Array.prototype.forEach.call(collapsable, el => { el.classList.remove('active') }) e.target.parentNode.classList.add('active') }) .container { width: 500px; margin: 0 auto; color:darkslategrey; } .item { margin: 10px 0; border-bottom: 1px solid #666; padding: 5px 10px; } .item.active h3 { color:aquamarine; } p { overflow: hidden; transition: height .5s ease; height: 0px; } .item.active p { height: 80px; } <div class="container"> <div class="item active"> <h3>I am a title</h3> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni minus neque nisi, rem doloribus unde quisquam, similique distinctio voluptate mollitia praesentium quo ut magnam ducimus nemo vitae soluta impedit harum?</p> </div> <div class="item"> <h3>I am a title</h3> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni minus neque nisi, rem doloribus unde quisquam, similique distinctio voluptate mollitia praesentium quo ut magnam ducimus nemo vitae soluta impedit harum?</p> </div> <div class="item"> <h3>I am a title</h3> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni minus neque nisi, rem doloribus unde quisquam, similique distinctio voluptate mollitia praesentium quo ut magnam ducimus nemo vitae soluta impedit harum?</p> </div> </div>
Render only selected element, React JS
I am trying to toggle class in one of my react component. The idea is to add class when the mouse enter and to remove the class when the mouse leave only in the element only the element in where the user perform the actions. However this is not the case as when the action is being performed all the element with the function are behaving equally. This is my code so far: export default class Projects extends Component{ constructor(){ super(); this.state = { isHovered : false } } //handle mouse enter handleMouseEnter = () =>{ this.setState({ isHovered : true }); } //handle mouse leave handleMouseLeave = () =>{ this.setState({ isHovered : false }); } //render component render(){ let display = ""; if(this.state.isHovered === true){ display = "active"; }else{ display = "disable"; } return( <section className="projects"> {/*section project wrapper*/} <div className="p-wrapper"> <h1 className="title">Projects</h1> <hr/> {/*projet wrapper*/} <div className="projects-wrapper"> {/*project item wrapper*/} <div className="project-item" onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>{/*FMA Web development*/} <div className={"p-description " + display}> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure quos dolorem, ipsa eaque minima saepe fugit hic libero recusandae! Obcaecati esse odit id incidunt vitae aperiam dicta atque blanditiis sint?</p> </div> <div className="p-image"> <img src="asset/img/fma_web.png" alt="FMA Web Development"/> </div> </div> <div className="project-item" onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>{/*Web development using php*/} <div className={"p-description " + display}> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure quos dolorem, ipsa eaque minima saepe fugit hic libero recusandae! Obcaecati esse odit id incidunt vitae aperiam dicta atque blanditiis sint?</p> </div> <div className="p-image"> <img src="asset/img/web_dev_php.png" alt="FMA Web Development Using PHP"/> </div> </div> <div className="project-item" onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>{/*Movie Catalog*/} <div className={"p-description " + display}> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure quos dolorem, ipsa eaque minima saepe fugit hic libero recusandae! Obcaecati esse odit id incidunt vitae aperiam dicta atque blanditiis sint?</p> </div> <div className="p-image"> <img src="asset/img/movie_catalog.png" alt="Movie Catalog"/> </div> </div> </div> </div> </section> ); } } I have read the use of key in the documentation and read other question especially this one LINK,however when I try to implement I do not get the desired result. =========================== EDIT This is what I get now. As you can see when I hover both of the element triggers. This is my CSS Code: /*Projects Start*/ .projects{ width: 100%; } .p-wrapper{ margin: 0 auto; width: 90%; height: 100%; } .projects-wrapper{ margin-top: 2rem; width: 100%; display: flex; justify-content: center; flex-wrap: wrap; } .project-item{ margin: 1rem; width: 30%; position: relative; box-shadow: 2px 3px 37px -5px rgba(0,0,0,0.84); } .p-description{ position: absolute; height: 100%; width: 100%; background-color: rgba(43, 40, 40, 0.61); color: white; } .p-description p { margin: 1rem; } .p-title{ margin: 1rem; } .active{ display: block; transition: all 2s ease-in; } .disable { display: none; }
How do I make the box below move ( accordion )
Didn't really know how to explain my problem in the title, my question is how do I make it so when I press the top box the other two boxes move down so you can see the text? The same goes for the other two boxes, if I press the middle the last box moves and when I press the last one the top and the middle stays. Plus the boxes has to go back to it's original place. Please I need help with this $(".faq,.faq2,.faq3").click(function() { $(this).find(".faq-box-more").toggleClass("open"); $(".faq,.faq2,.faq3").not(this).find(".faq-box-more").removeClass("open"); }); .faq, .faq2, .faq3 { height: 100px; width: 500px; background: red; position: relative; top: 100px; left: 50%; transform: translate(-50%, 0%); } .faq-box { position: relative; height: 100%; width: 100%; background: #333; cursor: pointer; padding: 0 20px; } .faq-box h2 { position: absolute; top: 50%; transform: translate(0, -50%); color: #fff; text-transform: uppercase; letter-spacing: 3px; font-size: 1.9rem; } .faq-box i { position: absolute; left: 96%; top: 50%; font-size: 3rem; transform: translate(-100%, -50%); color: #fff; } .faq-box-more { position: absolute; height: 0%; top: 100%; background-color: #222; color: #fff; width: 100%; } .faq-box-more p { position: absolute; width: 100%; padding: 20px; } .open { height: 140% !important; } <link href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet"/> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section> <div class="faq"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> <div class="faq2"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> <div class="faq3"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> </section>
see snippet below or jsfiddle if you don't want to use the jqueryUI accordion and want to learn how it actually works, it's something like this in CSS do not use absolute positioning on faq-box-more as it won't occupy any space. instead hide it with display:none for JQ first, you don't need to add different classes to all the faq divs, you can add one common class and then select the respective faq-box-more connected to the faq you click on , using jQuery methods below when you click on faq-box ( either one of them ) , in a variable ( for cleaner and concise code ) you store the corresponding faq-box-more . you do this by using sibling() method. searching .faq-box's ' brothers ' for the .faq-box-more . in HTML structure faq-box and faq-box-more are on the same level, therefore they are siblings then using an if condition you check if the previous selected faq-box-more is visible or not. IF YES -> close it , IF NO -> open IT . you close and open using slideUp() and slideDown() methods ( click on the methods to see more info about them ) then, you also want to find any previous opened faq-box-more and close them, so only one is opened at one time ( the one corresponding to the box you clicked on ) . to do this you use the parents() method to 'climb' up the HTML structure and get to faq and then using siblings() and find() you find the .faq-box-more , and if it is open, you hide it with slideUp() i think it's important that you try to understand the process behind the accordion and not just copy-paste it . if you have anymore questions on this subject, feel free to ask in the comments P.S. you had many problems in your code ( CSS ), it tried to correct some of them but also i wanted not to change too much your code. $(".faq-box").on("click",function() { var boxMore = $(this).siblings(".faq-box-more") if ($(boxMore).is(":visible")) { $(boxMore).slideUp() } else { $(boxMore).slideDown(500) } $(this).parents(".faq").siblings().find(".faq-box-more").slideUp() }); .faq { width: 500px; background: red; position: relative; left: 50%; transform: translate(-50%, 0%); } .faq-box { position: relative; height: 100%; width: 100%; background: #333; cursor: pointer; padding: 0 20px; } .faq-box h2 { color: #fff; text-transform: uppercase; letter-spacing: 3px; font-size: 1.9rem; } .faq-box i { position: absolute; left: 96%; top: 50%; font-size: 3rem; transform: translate(-100%, -50%); color: #fff; } .faq-box-more { background-color: #222; color: #fff; width: 100%; height:200px; display:none; } .faq-box-more p { position: absolute; width: 100%; padding: 20px; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section> <div class="faq"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> <div class="faq"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> <div class="faq"> <div class="faq-box"> <h2>lorem ipsum</h2> <i class="ion-ios-arrow-down"></i> </div> <div class="faq-box-more"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur numquam, atque nemo pariatur maiores eos harum, ab magni nisi quod, commodi ipsum totam vel nihil voluptatum vitae quisquam, qui amet!</p> </div> </div> </section>
Javascript Tabs Accordion Issue
I have created a tabs accordion which is working properly. However their behaviour is not as i want it to be. At the current tabs accordion when i press one of the tabs it will show the content inside it, and when i press another tab it will open also. What i would like to have happen is when i click one of the tabs to be the only one that is showing and the rest of the tabs to be closed. Hope someone can help me to add that extra code that i need to make it work. var tabsContainer = document.getElementById("tabsContainer"); var tabUl = document.getElementById("tabs-ul"); var tabOne = document.getElementById("tab-one"); var tabTwo = document.getElementById("tab-two"); var tabThree = document.getElementById("tab-three"); var tabOneContent = document.getElementById("tab-one-content"); var tabTwoContent = document.getElementById("tab-two-content"); var tabThreeContent = document.getElementById("tab-three-content"); function openTabOne() { if (tabOneContent.className == "toggleTab") { tabOneContent.className = ""; } else { tabOneContent.className = "toggleTab"; } } function openTabTwo() { if (tabTwoContent.className == "toggleTab") { tabTwoContent.className = ""; } else { tabTwoContent.className = "toggleTab"; } } function openTabThree() { if (tabThreeContent.className == "toggleTab") { tabThreeContent.className = ""; } else { tabThreeContent.className = "toggleTab"; } } tabOne.addEventListener("click", openTabOne); tabTwo.addEventListener("click", openTabTwo); tabThree.addEventListener("click", openTabThree); * { padding: 0px; margin: 0px; } body { font-family: sans-serif; font-weight: 14px; background: silver; } #tabsContainer { width: 50%; margin: 0 auto; border: 3px solid #a70d89; padding: 20px; box-shadow: 2px 2px 10px rgba(85, 85, 85, 0.77); ; } ul { list-style: none; } li { display: inline-block; padding: 5px 20px; background: #4c99ac; color: #7910c6; cursor: pointer; } #tabsContainer > div { margin: 20px 0px; display: none; } #tab-one-content.toggleTab, #tab-two-content.toggleTab, #tab-three-content.toggleTab { display: block; } <div id="tabsContainer"> <ul id="tabs-ul"> <li id="tab-one">Tab One</li> <li id="tab-two">Tab Two</li> <li id="tab-three">Tab Three</li> </ul> <div id="tab-one-content"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> <div id="tab-two-content"> Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> <div id="tab-three-content"> Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> </div>
You need to remove the class from the tabs that you don't want open anymore, here is a possible way to do it. var tabsContainer = document.getElementById("tabsContainer"); var tabUl = document.getElementById("tabs-ul"); var tabOne = document.getElementById("tab-one"); var tabTwo = document.getElementById("tab-two"); var tabThree = document.getElementById("tab-three"); var tabPanels = [ document.getElementById("tab-one-content"), document.getElementById("tab-two-content"), document.getElementById("tab-three-content") ]; function showTab(tabIndex) { for(var i = 0; i < tabPanels.length; i++) { tabPanels[i].className = i == tabIndex ? 'toggleTab' : ''; } } function openTabOne() { showTab(0); } function openTabTwo() { showTab(1); } function openTabThree() { showTab(2); } openTabOne(); tabOne.addEventListener("click", openTabOne); tabTwo.addEventListener("click", openTabTwo); tabThree.addEventListener("click", openTabThree); * { padding:0px; margin:0px; } body { font-family: sans-serif; font-weight: 14px; background:silver; } #tabsContainer { width:50%; margin:0 auto; border:3px solid #a70d89; padding:20px; box-shadow: 2px 2px 10px rgba(85, 85, 85, 0.77);; } ul { list-style: none; } li { display: inline-block; padding:5px 20px; background:#4c99ac; color:#7910c6; cursor: pointer; } #tabsContainer > div { margin: 20px 0px; display: none; } #tab-one-content.toggleTab, #tab-two-content.toggleTab, #tab-three-content.toggleTab { display: block; } <div id="tabsContainer"> <ul id="tabs-ul"> <li id="tab-one">Tab One</li> <li id="tab-two">Tab Two</li> <li id="tab-three">Tab Three</li> </ul> <div id="tab-one-content"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> <div id="tab-two-content"> Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> <div id="tab-three-content"> Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium. </div> </div>