So I have this great little nugget of code that I am trying to rewrite into plain JavaScript and CSS without jQuery.
jQuery.extend(jQuery.easing,{
easeInExpo: function (x, t, b, c, d) {
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
}
});
var nset = false;
$('button#hmenu').click(function(){
if(!nset){
$('ul#nav').delay(35).slideDown(300,'easeInExpo');
$('button#hmenu').addClass('active');
nset = true;
} else {
$('ul#nav').slideUp(550);
nset = false;
$('button#hmenu').removeClass('active');
}
})
I'm looking at some CSS transitions that use easing but just wondering what the options are? In my code I have a slideDown and up easing functions. This is used in production for a mobile menu nav.
Update:
This github repo (You don't need jQuery) has a really comprehensive list of common jQuery functions, all rewritten in vanilla Javascript.
It includes animations, query selectors, ajax, events and other advanced jQuery features.
The slightly older youmightnotneedjquery.com is also very good, particularly if you need to support older IE versions.
You can achieve an easeInExpo style animation by using the following CSS, as provided by this website:
transition: all 500ms cubic-bezier(0.950, 0.050, 0.795, 0.035);
The below example illustrates this easing property on the height of a div. I've updated it to match the delay you've added in jQuery when clicked (35ms), the timings (300ms and 550ms respectively), and jQuery's default easing ('swing') – as provided by this answer – when it's closed:
let expandable = document.getElementById('expandable');
let expandButton = document.getElementById('expand-button');
expandButton.addEventListener('click', () => {
expandable.classList.toggle('expanded');
});
#expandable {
background: red;
transition: all 550ms cubic-bezier(.02, .01, .47, 1);
height: 0px;
width: 100px;
transition-delay: 0ms;
}
#expandable.expanded {
height: 100px;
transition-delay: 35ms;
transition: all 300ms cubic-bezier(0.950, 0.050, 0.795, 0.035);
}
<div id="expandable"></div>
<br />
<button id="expand-button">Toggle expand</button>
There's a little bit of magic needed here in order to get your collapsible component to expand to a variable height. If you are just expanding to the same height each time, say 100px, that's a simple as creating a single class such as "expanded" and then adding and removing that class as a boolean switch.
We'll still be using a boolean switch for variable heights, but we'll also need to get the heights of each expandable element using JavaScript, and then refresh those height values if the size of the user's window changes to account for text-wrapping, image resizing, etc.
We can achieve rather simply using custom CSS properties (variables), with a fallback value to unset, meaning that when to variable height is present, the box will expand to show all contents without an animation as a last resort, but in most if not all cases (and for all modern browsers) the custom CSS variable should be the ideal solution for unique values per section.
Here it is in action (below), with both a toggle and accordion example, with a cubic bezier easing function used to closely match the easeInExpo function you supplied in your original question. I pulled this easing function cubic-bezier(0.95, 0.05, 0.795, 0.035) from easings.net/en#easeInExpo where they have a pure CSS easing for easeInExpo and many others.
Simple Example
const expandables = document.querySelectorAll('.expandable');
const setInnerHeights = () => {
for (const expandable of expandables) {
expandable.style.setProperty('--inner-height', Array.from(expandable.children).map(child => child.offsetHeight).reduce((a, c) => a + c, 0) + 'px');
}
};
setInnerHeights();
document.addEventListener('click', e => {
if (e.target?.matches('.expand-trigger')) {
const expandable = e.target.nextElementSibling;
expandable.classList[expandable.classList.contains('expanded') ? 'remove' : 'add']('expanded');
}
});
window.addEventListener('resize', setInnerHeights);
html {
height: 100%;
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
body {
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
min-height: 100%;
padding: 20px;
}
.expandable {
max-height: 0;
overflow: hidden;
transition: max-height 0.25s cubic-bezier(0.95, 0.05, 0.795, 0.035);
text-align: left;
}
.expandable > p {
margin: 0;
padding: 10px 0;
}
.expandable.expanded {
--content-height: calc(var(--inner-height) + 20px);
max-height: var(--content-height, unset);
}
<button class="expand-trigger">Expand #1</button>
<div class="expandable">
<p>Lorem ipsum dolor sit amet.</p>
</div>
<button class="expand-trigger">Expand #2</button>
<div class="expandable">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
</div>
<button class="expand-trigger">Expand #3</button>
<div class="expandable">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
<p>Integer convallis lectus eu felis bibendum, vel lacinia metus imperdiet. Maecenas vulputate, quam vitae tempus pretium, erat felis euismod risus, nec blandit leo mi eget purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at neque laoreet, egestas dui ut, bibendum lorem. Maecenas elementum odio a congue facilisis. Vivamus risus urna, vestibulum egestas sem nec, lacinia volutpat metus. Suspendisse potenti. Suspendisse ullamcorper commodo libero, sed rhoncus nibh porta in. Donec mi felis, posuere luctus varius ac, faucibus vitae erat.</p>
</div>
Complex Example
const initAccordions = () => {
const getNode = selector => document.querySelector(selector),
getNodes = selector => Array.from(document.querySelectorAll(selector)),
findChildren = (node, selector) => Array.from(node.children).filter(e => e.matches?.(selector)),
findChild = (node, selector) => Array.from(node.children).find(e => e.matches?.(selector)),
_addInput = (node, position, id, checked) => node.insertAdjacentHTML(position, `<input type="radio" name="accordion-${id}"${checked ? ' checked="checked"' : ''}>`),
setInnerHeight = node => {
const height = Array.from(node.children).map(child => child.offsetHeight).reduce((a, c) => a + c, 0) + 'px';
node.style.setProperty('--inner-height', height);
},
accordions = Array.from(document.querySelectorAll('.accordion'));
let accordionIndex = 0;
for (const accordion of accordions) {
const isToggle = accordion.dataset?.type === 'toggle',
panels = findChildren(accordion, '.accordion--panel');
let panelIndex = 0;
for (const panel of panels) {
const title = findChild(panel, '.accordion--panel--title'),
content = findChild(panel, '.accordion--panel--content'),
addInput = (node, position, checked) => _addInput(node, position, accordionIndex + (isToggle ? '-' + panelIndex : ''), checked);
setInnerHeight(content);
addInput(title, 'beforebegin');
addInput(title, 'afterbegin', true);
panelIndex++;
}
accordionIndex++;
}
window.addEventListener('resize', () => {
const panelContents = Array.from(document.querySelectorAll('.accordion > .accordion--panel > .accordion--panel--content'));
for (const content of panelContents) setInnerHeight(content);
});
};
initAccordions();
html {
height: 100%;
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 100%;
padding: 20px;
}
.accordion--panel > [type=checkbox],
.accordion--panel > [type=radio], .accordion--panel--title > [type=checkbox],
.accordion--panel--title > [type=radio] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.accordion--panel > [type=checkbox]:checked,
.accordion--panel > [type=radio]:checked, .accordion--panel--title > [type=checkbox]:checked,
.accordion--panel--title > [type=radio]:checked {
display: none;
}
.accordion--panel {
border-radius: 7px;
}
.accordion--panel--title {
background-color: #ccc;
}
.accordion--panel--content {
box-shadow: inset 0 0 0 2px #ccc;
border-radius: 0 0 7px 7px;
}
.accordion {
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
max-width: 500px;
}
.accordion--panel {
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.accordion--panel > [type=checkbox],
.accordion--panel > [type=radio] {
z-index: 1;
}
.accordion--panel--title, .accordion--panel--content {
padding-inline: 15px;
}
.accordion--panel--title {
position: relative;
padding-block: 10px;
}
.accordion--panel--content {
max-height: 0;
overflow: hidden;
transition: max-height 0.25s cubic-bezier(0.95, 0.05, 0.795, 0.035);
}
.accordion--panel--content--inner > p:first-child {
margin-top: 10px;
}
.accordion--panel--content--inner > p:last-child {
margin-bottom: 10px;
}
[type=checkbox]:checked ~ .accordion--panel--content, [type=radio]:checked ~ .accordion--panel--content {
--content-height: calc(var(--inner-height) + 20px);
max-height: var(--content-height, unset);
}
<h2>Accordion Demo</h2>
<div class="accordion" data-type="accordion">
<div class="accordion--panel">
<div class="accordion--panel--title">Title #1</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
<div class="accordion--panel">
<div class="accordion--panel--title">Title #2</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
</div>
</div>
</div>
<div class="accordion--panel">
<div class="accordion--panel--title">Title #3</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
<p>Integer convallis lectus eu felis bibendum, vel lacinia metus imperdiet. Maecenas vulputate, quam vitae tempus pretium, erat felis euismod risus, nec blandit leo mi eget purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at neque laoreet, egestas dui ut, bibendum lorem. Maecenas elementum odio a congue facilisis. Vivamus risus urna, vestibulum egestas sem nec, lacinia volutpat metus. Suspendisse potenti. Suspendisse ullamcorper commodo libero, sed rhoncus nibh porta in. Donec mi felis, posuere luctus varius ac, faucibus vitae erat.</p>
</div>
</div>
</div>
</div>
<h2>Toggle Demo</h2>
<div class="accordion" data-type="toggle">
<div class="accordion--panel">
<div class="accordion--panel--title">Title #1</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
<div class="accordion--panel">
<div class="accordion--panel--title">Title #2</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
</div>
</div>
</div>
<div class="accordion--panel">
<div class="accordion--panel--title">Title #3</div>
<div class="accordion--panel--content">
<div class="accordion--panel--content--inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mi purus, interdum id mattis et, posuere nec urna. Mauris in ornare sem. Phasellus non eros augue. Fusce tempus bibendum mauris, vel luctus est viverra eget. Cras vitae lectus magna. Integer vulputate est ut felis dictum consectetur. Nunc vitae enim at sem rhoncus aliquet et id risus. Etiam faucibus quis turpis eu pellentesque. Aliquam dictum lorem nec orci finibus commodo. Etiam tincidunt lacinia consectetur. Praesent tortor lorem, imperdiet sed varius vel, varius ac quam. Vestibulum aliquam lorem sem, sit amet imperdiet purus commodo eu. Integer a iaculis tortor.</p>
<p>Integer convallis lectus eu felis bibendum, vel lacinia metus imperdiet. Maecenas vulputate, quam vitae tempus pretium, erat felis euismod risus, nec blandit leo mi eget purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at neque laoreet, egestas dui ut, bibendum lorem. Maecenas elementum odio a congue facilisis. Vivamus risus urna, vestibulum egestas sem nec, lacinia volutpat metus. Suspendisse potenti. Suspendisse ullamcorper commodo libero, sed rhoncus nibh porta in. Donec mi felis, posuere luctus varius ac, faucibus vitae erat.</p>
</div>
</div>
</div>
</div>
Other CSS easing functions are available at easings.net.
You can also customize your easing function visually using Chrome's DevTools by adding either the transition or transition-timing-function properties to any element with the value of ease, then clicking the square curve icon next to the word ease and dragging either of the circular handles.
Related
I want to show a div only if the page has scrollbars, and hide it if not. I want to do this in either pure CSS or JavaScript (if impossible in CSS).
I've found a question on Stack Exchange, but it's infested with that garbage jQuery cancer, so it's useless. I'm talking about pure JavaScript -- not jCancer.
Here's a pure JS solution, using this function:
const isScrollable = elem => elem.scrollHeight > elem.clientHeight;
Edit (description):
The function returns true if the element is scrollable, false otherwise.
Example:
const isScrollable = elem => elem.scrollHeight > elem.clientHeight;
// make scrollable divs have a red border
document.querySelectorAll("div").forEach(div => {
if (isScrollable(div)) div.style.borderColor = "red";
});
div {
border: 1px solid grey;
width: 200px;
overflow: auto;
margin-bottom: 1rem;
}
div#div1 {
height: 100px;
}
div#div2 {
height: 170px;
}
<div id="div1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras maximus arcu quis mi eleifend tristique. Curabitur convallis tellus eget volutpat luctus. Fusce molestie molestie ante, vel fermentum erat. Fusce tempor erat eget dolor ultrices interdum. Pellentesque sed placerat nulla. Duis consequat, lorem quis vehicula lacinia, libero leo tincidunt odio, et porta ex turpis malesuada lorem. Proin sapien metus, facilisis sed urna non, vehicula commodo velit. Etiam venenatis laoreet neque vel sollicitudin. Suspendisse lacinia, lectus hendrerit dapibus laoreet, dui lorem condimentum enim, a vulputate ex ipsum ut nibh.
</div>
<div id="div2">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras maximus arcu quis mi eleifend tristique. Curabitur convallis tellus eget volutpat luctus. Fusce molestie molestie ante, vel fermentum erat.
</div>
I have already tried with fixed and sticky position.Let's say we have two columns in our website, main column and sidebar.And our side column has contents longer than the height of the view port( like in reddit website as it contains footer and some ads).With fixed position , side bar doesn't scroll on page scroll.With sticky position , the side bar is initially sticky and scrolls only when the main column is ending. In reddit side bar , the right side bar scrolls along with page scroll. When the sidebar reaches the end of its content , it becomes sticky to the view port. How can i achieve that?
Here is the code for css
.sidenav { position: sticky; top: 20px; right: 0; left: 0; float: left; padding:10px; z-index:999998; }
.sidenav a {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 25px;
color: #2196F3;
display: block; }
.main {
margin-left: 140px;
font-size: 28px;
padding: 0px 10px; }
code for html
<div class="sidenav">
About
Services
Clients
Contact
About
</div>
<div class="main">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.
<p>
</div>
You can store a specific scroll position value ( number of pixels) on the page at which you'd like to switch from the static scroll bar positioning over to fixing it to the bottom of the page. I used the start of the sidebar + the height of the sidebar - the window height + the padding I want below the sidebar. Then you just check the scroll position of the window when the document is scrolled and if it is past the value you stored, you add a class that switches its position to fixed. This snippet uses jQuery to accomplish the behavior in just a few lines.
const sidebar = $('.sidebar');
const fixedScrollPosition = sidebar.offset().top + sidebar.outerHeight() - $(window).innerHeight() + 10;
$(document).on('scroll', function() {
sidebar.toggleClass('fixed', $(window).scrollTop() > fixedScrollPosition);
});
body {
font-size: 0;
padding: 0;
}
p {
height: 200px;
background: red;
}
p:last-child {
margin: 0;
}
.page-content {
width: calc( 100% - 160px);
margin-right: 10px;
font-size: initial;
box-sizing: border-box;
display: inline-block;
vertical-align: top;
}
.sidebar {
width: 150px;
font-size: initial;
box-sizing: border-box;
vertical-align: top;
display: inline-block;
}
.sidebar.fixed {
position: fixed;
bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="page-content">
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
</div>
<div class="sidebar">
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
</div>
Edited:
HTML:
<div class="sidenav">
About
Services
Clients
Contact
<div class="sticky-tag">
sticky
sticky
</div>
</div>
<div class="main">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.
<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisi nec mi elementum pretium sit amet ac leo. Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh.
<br>Vestibulum pellentesque, nisl sed bibendum mollis, neque quam auctor lorem, a mollis erat risus id purus. Etiam vel semper nibh. Praesent ac augue ultricies, auctor orci sed, mollis metus. Nunc in tempus lectus. Duis id sapien dignissim, lobortis velit ornare, fringilla ex.
<p>
</div>
CSS:
.sidenav {
margin-top: 20px;
float: left;
padding: 10px;
z-index: 999998;
width: 12%;
height: 100vh;
}
.sidenav a {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 25px;
color: #2196F3;
display: block;
}
.sidenav .sticky-tag {
position: sticky;
top: 20px;
}
.main {
width: 88%;
margin-left: 12%;
font-size: 28px;
padding: 0px 15px;
}
I have found this Codepen that I wish to use and it's perfect apart from the fact that once you open and close a card, the preview text reveals more than before it was opened.
https://codepen.io/Beardwig/pen/RZExaj
I think it has something to do with this class however I'm not entirely sure
<div class='expd-truncate'>
This is the link to the Codepen, any help is greatly appreciated.
Thanks
The text is truncated by javascript.
When closing the card, the javascript function that truncates again the text is called too much early:
$('.expd-truncate',thisCard).snipper({height: '60px'});
should be called at the very end of your code
The problem is not the class, nor in fact the CSS at all, but rather that after expanding and contracting the card there is too much content inside of the div.expd-truncate and the p tag within it - prior to the expansion it is a call to the .snipper method when the document is ready which truncates that content and appends an ellipsis to keep the content from being too long. I'm referring to this part of the code on line 74 of the CodePen:
$(document).ready(function(){
$('.expd-truncate').snipper({height: '60px'});
});
The bug is caused by the .snipper method being called prior to the alteration of the classes governing the display of the content being snipped when the button to retract/un-expand the card is clicked. Thus, when the card is retracted, the content gets snipped, then the classes are changed and the layout changes accordingly and the content reflows, and now the content is ultimately a different height than it was when it was snipped.
So the solution is to simply call the .snipper method after the alteration of the classes (ie line 117 ($('.expd-truncate',thisCard).snipper({height: '60px'});) should be below lines 118-121).
See this fork I made of the CodePen above for a working demonstration:
https://codepen.io/anon/pen/GBezWG
Or check out the JS in this working snippet, which is equivalent but with plain HTML and CSS:
(function($){
"use strict"
$.fn.snipper = function(options) {
var opts = $.extend({}, $.fn.snipper.defaults, options),
trimText = function($el, height, ellipsis) {
// Make sure HTML entities only count as one character
var ellipsisNumChars = ellipsis.replace(/&[^;]+?;/g, '.').length;
while ($el.outerHeight() > height) {
if ($el.text().length <= ellipsisNumChars) {
break;
}
$el.html(function(i, text) {
if (/\s/.test(text)) {
return text.replace(/\s*(\S)*$/, ellipsis);
}
// If there is just one really long string without spaces
// start stripping the last character and concatinating the ellipsis
return text.replace(new RegEx('.{' + (ellipsisNumChars + 1) + '}$'), ellipsis);
});
}
};
this.each(function(){
var $el = $(this),
fullText = opts.fullText || $el.data('snipper:fullText'),
height = opts.height,
ellipsis = opts.ellipsis || '';
// If height is a function get its return value
if (typeof(height) === 'function') {
height = height.apply(this);
}
if (!height) {
return;
}
height = parseInt(height, 10);
if (isNaN(height)) {
return;
}
if (fullText) {
if (typeof(fullText) === 'function') {
fullText = fullText.apply(this);
}
$el.html(fullText);
} else {
$el.data('snipper:fullText', $el.html());
}
trimText($el, height, ellipsis);
});
return this;
};
$.fn.snipper.defaults = {
ellipsis: '…'
};
}(jQuery))
//none/grow pulse/grow, bounceIn/grow, BounceInUp/slide, fadeInUp/slide, lightSpeedIn/slide, rotateInUpLeft/fade, rollIn/slide, zoomIn/fade, slideInUp/slide
var speed = 300,
animClassIn = "pulse",
animClassOut = "fadeIn",
expandStyle = "grow";
$(document).ready(function(){
$('.expd-truncate').snipper({height: '60px'});
});
//
//Expand
//
$(document).on("click",".wrap-expd-card .expd-card-toggle" , function() {
var thisCard = $(this).closest(".expd-card"),
cardLeft = thisCard.offset().left,
cardTop = thisCard.offset().top - $(window).scrollTop();
$('.expd-truncate',thisCard).snipper({height: '9999px'});
thisCard.parent(".wrap-expd-card").addClass("expd-hold");
thisCard.prependTo("body");
$("body").addClass("expd-body");
thisCard.addClass("expd-pre-anim").css({left: cardLeft, top: cardTop});
thisCard.removeClass("out-anim "+animClassOut);
thisCard.css('opacity');
if(expandStyle == "grow") {
thisCard.removeClass("expd-pre-anim").addClass("expd-active").css({left: 0, top: 0, transition: "all "+speed+"ms ease", opacity: 1});
thisCard.addClass(animClassIn);
} else if (expandStyle == "slide") {
thisCard.animate({
top: '100%'
}, 100, function () {
thisCard.removeClass("expd-pre-anim").addClass("expd-active");
}).promise().done(function () {
thisCard.addClass(animClassIn);
});
} else if (expandStyle == "fade") {
thisCard.removeClass("expd-pre-anim").addClass("expd-active").css({left: 0, top: 0,opacity: 1, transition: "opacity "+speed+"ms"});
thisCard.addClass(animClassIn);
}
});
//
//Retract
//
$(document).on("click",".expd-body .expd-card-toggle", function() {
var thisCard = $(this).closest(".expd-card"),
cardLeft = $(".expd-hold").offset().left,
cardTop = $(".expd-hold").offset().top - $(window).scrollTop();
thisCard.removeClass("expd-active "+animClassIn).addClass("expd-pre-anim").css({left: cardLeft, top: cardTop, opacity: 0});
thisCard.animate({scrollTop:0},speed);
//setTimeout(function(){
thisCard.removeClass("expd-pre-anim").css({left: 0, top: 0, opacity: 1});
thisCard.appendTo(".wrap-expd-card.expd-hold").addClass(animClassOut);
$(".wrap-expd-card").removeClass("expd-hold");
$("body").removeClass("expd-body");
$('.expd-truncate',thisCard).snipper({height: '60px'});
//}, 0);//
});
body {
background: #333;
}
.expd-card,
.expd-card * {
box-sizing: border-box;
}
.wrap-expd-card {
width: 320px;
height: 320px;
float: left;
margin: 16px;
}
.expd-card.fadeIn {
animation-duration: 300ms;
animation-delay: 0ms;
}
.expd-card {
font-family: Roboto, sans-serif;
color: #7c7c7c;
background: #fff;
position: relative;
width: 320px;
height: 320px;
border: 1px solid #ccc;
overflow: hidden;
animation-duration: 400ms;
animation-delay: 200ms;
animation-iteration-count: 1;
}
.expd-card .expd-card-body-wrap {
max-width: 960px;
margin: 0 auto;
}
.expd-card .expd-card-body-wrap .expd-card-img {
height: 0px;
padding-bottom: 56.25%;
background: #bbb;
}
.expd-card .expd-card-body-wrap .expd-card-content {
margin: 18px 16px;
position: relative;
}
.expd-card .expd-card-body-wrap .expd-card-content .expd-card-toggle {
position: absolute;
cursor: pointer;
height: 40px;
width: 40px;
background: #f00;
right: 16px;
top: -36px;
border-radius: 50%;
}
.expd-card .expd-card-body-wrap .expd-card-content .expd-heading h2 {
color: #383838;
font-size: 20px;
margin: 0;
}
.expd-card .expd-card-body-wrap .expd-card-content .expd-heading strong {
color: #585858;
font-size: 14px;
}
.expd-card .expd-card-body-wrap .expd-card-content p {
font-size: 14px;
margin: 10px 0px;
}
.expd-body {
overflow: hidden;
}
.expd-card.expd-pre-anim {
position: fixed;
z-index: 99;
}
.expd-card.expd-active {
position: fixed;
z-index: 99;
top: 0 !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
width: 100% !important;
height: 100% !important;
overflow: scroll;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<title>fiddle</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="script.js"></script>
</head>
<body class="">
<div class="wrap-expd-card">
<div class="expd-card animated fadeIn" style="left: 0px; top: 0px; transition: all 300ms ease 0s; opacity: 1;">
<div class="expd-card-body-wrap">
<div class="expd-card-img">
</div>
<div class="expd-card-content">
<div class="expd-card-toggle">
</div>
<div class="expd-heading">
<h2>Lorem Ipsum</h2>
<strong>Subtitle</strong>
</div>
<div class="expd-truncate">
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Nulla quis lorem ut libero malesuada feugiat. Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p>
<p>Donec rutrum congue leo eget malesuada. Nulla porttitor accumsan tincidunt. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Vivamus suscipit tortor eget felis porttitor volutpat.</p>
<p>Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec rutrum congue leo eget malesuada.</p>
<p>Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec sollicitudin molestie malesuada. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla porttitor accumsan tincidunt. Pellentesque in ipsum id orci porta dapibus.</p>
</div>
</div>
</div>
</div>
</div>
<div class="wrap-expd-card">
<div class="expd-card animated">
<div class="expd-card-body-wrap">
<div class="expd-card-img">
</div>
<div class="expd-card-content">
<div class="expd-card-toggle">
</div>
<div class="expd-heading">
<h2>Lorem Ipsum</h2>
<strong>Subtitle</strong>
</div>
<div class="expd-truncate">
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Nulla quis lorem ut libero malesuada feugiat. Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p>
<p>Donec rutrum congue leo eget malesuada. Nulla porttitor accumsan tincidunt. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Vivamus suscipit tortor eget felis porttitor volutpat.</p>
<p>Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec rutrum congue leo eget malesuada.</p>
<p>Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec sollicitudin molestie malesuada. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla porttitor accumsan tincidunt. Pellentesque in ipsum id orci porta dapibus.</p>
</div>
</div>
</div>
</div>
</div>
<div class="wrap-expd-card">
<div class="expd-card animated">
<div class="expd-card-body-wrap">
<div class="expd-card-img">
</div>
<div class="expd-card-content">
<div class="expd-card-toggle">
</div>
<div class="expd-heading">
<h2>Lorem Ipsum</h2>
<strong>Subtitle</strong>
</div>
<div class="expd-truncate">
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Nulla quis lorem ut libero malesuada feugiat. Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p>
<p>Donec rutrum congue leo eget malesuada. Nulla porttitor accumsan tincidunt. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Vivamus suscipit tortor eget felis porttitor volutpat.</p>
<p>Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec rutrum congue leo eget malesuada.</p>
<p>Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec sollicitudin molestie malesuada. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla porttitor accumsan tincidunt. Pellentesque in ipsum id orci porta dapibus.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
I have bootstrap modal which contains scrollable div id=moreContent and modal is open when a button is clicked. but the problem if I close the div with the scroll bar and then I try to reopen the modal the scroll function is also called. what am I doing wrong here.
$(document).ready(function() {
$("#buttonId").click(function() {
$('#myModal').openModal();
});
$("#moreContent").scroll(function() {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this[0].scrollHeight) {
console.log("this should be called only if manually scrolled ??");
}
}
});
});
#myModal {
max-height: 700px;
height: 700px;
min-height: 700px;
max-width: 912px;
min-width: 912px;
width: 912px;
}
#moreContent {
overflow-y: auto;
max-height: 300px;
min-height: 300px;
}
<div id="myModal" class="modal confirm-dialog">
<div class="modal-content">
<div id="moreContent">
<div id="moreSupervisorContent"></div>
<div id="moreSubordinateContent" class="hidden"></div>
</div>
</div>
This is because your modal is changing the size of the document. When the document changes size, the scroll position changes, thus triggering a scroll event.
This is most likely due to the fact that your modal has a fixed height. Setting fixed sizes is typically a bad idea in web development since you can't predict how big someone's screen or browser will be.
To solve it, you should style your modal an absolute or fixed position, set it to 100% height and have it handle the overflow instead of #moreContent. The position will keep the document from growing and the modal will only show scrollbars if its content gets larger than it is.
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
background: rgba(0, 0, 0, 0.8);
overflow: auto;
}
.modal__content {
height: 700px;
width: 60%;
margin: 30px auto;
padding: 30px;
background: #CCC;
}
<div class="modal">
<div class="modal__content">
<h3>This is the modal content</h3>
<p>This is some content inside the modal and it is fixed to 700px height</p>
</div>
</div>
<h1>This is the page</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vestibulum luctus leo pharetra sodales. Donec quis imperdiet odio, interdum hendrerit libero. Phasellus sollicitudin pellentesque turpis, vitae sagittis augue sagittis sit amet. Aenean pretium augue in pharetra tempor. Aenean tempus vulputate dui, eget blandit eros vulputate a. Morbi et laoreet metus, non sollicitudin ex. Phasellus egestas, magna et malesuada bibendum, dolor nisl gravida nunc, sit amet pulvinar nisl leo eu neque. Etiam eget orci ac velit porttitor euismod. Aenean accumsan condimentum egestas. Donec dictum laoreet mi, eu auctor ante sagittis id. Integer lacinia bibendum porta.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vestibulum luctus leo pharetra sodales. Donec quis imperdiet odio, interdum hendrerit libero. Phasellus sollicitudin pellentesque turpis, vitae sagittis augue sagittis sit amet. Aenean pretium augue in pharetra tempor. Aenean tempus vulputate dui, eget blandit eros vulputate a. Morbi et laoreet metus, non sollicitudin ex. Phasellus egestas, magna et malesuada bibendum, dolor nisl gravida nunc, sit amet pulvinar nisl leo eu neque. Etiam eget orci ac velit porttitor euismod. Aenean accumsan condimentum egestas. Donec dictum laoreet mi, eu auctor ante sagittis id. Integer lacinia bibendum porta.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vestibulum luctus leo pharetra sodales. Donec quis imperdiet odio, interdum hendrerit libero. Phasellus sollicitudin pellentesque turpis, vitae sagittis augue sagittis sit amet. Aenean pretium augue in pharetra tempor. Aenean tempus vulputate dui, eget blandit eros vulputate a. Morbi et laoreet metus, non sollicitudin ex. Phasellus egestas, magna et malesuada bibendum, dolor nisl gravida nunc, sit amet pulvinar nisl leo eu neque. Etiam eget orci ac velit porttitor euismod. Aenean accumsan condimentum egestas. Donec dictum laoreet mi, eu auctor ante sagittis id. Integer lacinia bibendum porta.</p>
Sorry for not being clearer here guys. Thanks for the quick responses.
I'm looking to use this snippet of js to equalise the heights on various divs. It only appears to work for for divs with class "jsEq-1" (shown in the red box in my snippet.
I'm also expecting the green and yellow boxes to equalise out in height... so all green boxes will be the same height and all yellow boxes will be the same height. So although the content in each box is a different length I want the containers to be equal heights and everything to line up.
The green boxes have a class of jsEq-2 and the yellow boxes have a class of jsEq3 but my script doesn't seem to work on divs with class of "jsEq-2" or "jsEq-3" "jsEq4" etc etc.
I'd like it to loop through any divs with class beginning with "jsEq-" and any number at the end but I just can't figure this out.
Thanks in advance for any tips.
$(window).load(function() {
$.fn.extend({
equalHeights: function(){
var top=0;
var row=[];
var classname=('equalHeights'+Math.random()).replace('.','');
$(this).each(function(){
var thistop=$(this).offset().top;
if (thistop>top) {
$('.'+classname).removeClass(classname);
top=thistop;
}
$(this).addClass(classname);
$(this).height('auto');
var h=(Math.max.apply(null, $('.'+classname).map(function(){ return $(this).outerHeight(); }).get()));
$('.'+classname).outerHeight(h);
//$('.'+classname).css("min-height",(h));
}).removeClass(classname);
}
});
var equalizeMe = function() {
var $highest = 1;
$("[class^='jsEq-']").each(function(idx,ele){
var $classname = $(this).attr("class");
var $parts = $classname.split("-");
if($highest < $parts[1]){
$highest = $parts[1];
}
});
for(var $i=1; $i<$highest+1; $i++){
$(".jsEq-"+$i).equalHeights();
}
};
//------------------------------------------------------
// VIEWPORT RESIZING
$(window).resize(function () {
equalizeMe();
}).trigger("resize");
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h2, p {
margin-bottom: 0;
}
.column {
float: left;
width: 30%;
margin: 0 1%;
background: blue;
}
.header {
background: red;
}
.body {
background: green
}
.footer {
background: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<div class="column">
<div class="header jsEq-1">
<h2>Short heading</h2>
</div>
<div class="body jsEq-2">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus. Nulla pretium lorem eu justo tincidunt, eget faucibus ex egestas. Aliquam commodo enim at lorem blandit sodales. Aenean sed tellus vitae nisl imperdiet molestie eget id mauris. Praesent non ullamcorper sapien.</p>
</div>
<div class="footer jsEq-3">
<p>Duis feugiat id nunc a maximus.</p>
</div>
</div>
<div class="column">
<div class="header jsEq-1">
<h2>Medium heading blandit id sollicitudin eget, pellentes</h2>
</div>
<div class="body jsEq-2">
<p>Pellentesque quam augue, blandit id sollicitudin eget, pellentesque in nunc. Curabitur sed purus justo. Maecenas aliquet, purus non porta vestibulum, dolor nisi congue nisi, id tincidunt quam nisi non lacus. Morbi in nunc eget neque rhoncus dapibus. Morbi id orci ligula. Duis elementum, sem eget tempus bibendum, est purus vestibulum felis, ut aliquam sem felis id massa. Aliquam non imperdiet ligula, vitae laoreet nisl. Fusce vehicula metus nec lectus luctus tempor. Integer laoreet ligula quis magna dignissim, sed convallis tellus finibus. Mauris arcu justo, dignissim congue maximus vel, faucibus eu ipsum. Duis ullamcorper mi in risus finibus fermentum. Pellentesque ut metus feugiat arcu ullamcorper elementum et sed nunc. Donec luctus diam a orci elementum, in sollicitudin mauris scelerisque. Morbi aliquet enim enim. Nullam quis pretium lectus. </p>
</div>
<div class="footer jsEq-3">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
</div>
<div class="column">
<div class="header jsEq-1">
<h2>Long heading pellentesque quam augue, blandit id sollicitudin eget, pellentesque in nunc</h2>
</div>
<div class="body jsEq-2">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
<div class="footer jsEq-3">
<p>Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
</div>
The [class^='jsEq-'] selector in the equalizeMe function is targeting elements having classes that begin with the string jsEq-, but no such elements exist. All your "class" values actually begin with either "header", "body", or "footer".
Therefore, $highest is never modified from its initial value of 1, so the subsequent for loop runs only once, which is why only the red boxes have equal heights.
To resolve this issue, target elements whose "class" values contain the string "jsEq-" instead.
Just change this line:
$("[class^='jsEq-']").each(function(idx,ele){
To this:
$("[class*='jsEq-']").each(function(idx,ele){
This code seems to work fine. The problem could be in the html, equalHeights function, or the version of jQuery being used.
After OP Edit: The selector
$("[class^='jsEq-']")
was using ^=, which only matches class names that start with the given string. Since you have other class names that are appearing first, you need to use *= to select any tags whose class name contains the given string.
$("[class*='jsEq-']")
I also switched
var $parts = $classname.split("-");
if($highest < $parts[1]){
$highest = $parts[1];
}
to
var $classNumber = parseInt($classname.substring($classname.indexOf("jsEq-")+5));
if($highest < $classNumber){
$highest = $classNumber;
}
This is safer in case you have other classes with a dash in them (as is very common with bootstrap for example).
var equalizeMe = function() {
var $highest = 1;
$("[class*='jsEq-']").each(function(idx,ele){
var $classname = $(this).attr("class");
// this extracts the number after 'jsEq'
// otherwise, other dash-classes would break your split("-") array method
var $classNumber = parseInt($classname.substring($classname.indexOf("jsEq-")+5));
if($highest < $classNumber){
$highest = $classNumber;
}
});
for(var $i=1; $i<$highest+1; $i++){
// This is showing the loop works. Check equalHeights()
$(`.jsEq-${$i}`).html(`.jsEq-${$i} highest = ${$highest}`);
}
};
equalizeMe();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test jsEq-1 foo foo-baz"></div>
<div class="text foo-bar jsEq-2"></div>
<div class="stuff jsEq-3"></div>
<div class="foo jsEq-4 dash-this"></div>
<div class="bar jsEq-5 dash-that"></div>
Thanks guys
#MJH - I ended up moving the for loop inside the each() function and changing to [class*='jsEq-'] and it now appears to work. See updated snippet.
$(window).load(function() {
$.fn.extend({
equalHeights: function(){
var top=0;
var row=[];
var classname=('equalHeights'+Math.random()).replace('.','');
$(this).each(function(){
var thistop=$(this).offset().top;
if (thistop>top) {
$('.'+classname).removeClass(classname);
top=thistop;
}
$(this).addClass(classname);
$(this).height('auto');
var h=(Math.max.apply(null, $('.'+classname).map(function(){ return $(this).outerHeight(); }).get()));
$('.'+classname).outerHeight(h);
//$('.'+classname).css("min-height",(h));
}).removeClass(classname);
}
});
var equalizeMe = function() {
var $highest = 1;
$("[class*='jsEq-']").each(function(idx,ele){
var $classname = $(this).attr("class");
var $parts = $classname.split("-");
if($highest < $parts[1]){
$highest = $parts[1];
}
for(var $i=1; $i<$highest+1; $i++){
$(".jsEq-"+$i).equalHeights();
}
});
};
//------------------------------------------------------
// VIEWPORT RESIZING
$(window).resize(function () {
equalizeMe();
}).trigger("resize");
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h2, p {
margin-bottom: 0;
}
.column {
float: left;
width: 30%;
margin: 0 1%;
background: blue;
}
.header {
background: red;
}
.body {
background: green
}
.footer {
background: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<div class="column">
<div class="header jsEq-1">
<h2>Short heading</h2>
</div>
<div class="body jsEq-2">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus. Nulla pretium lorem eu justo tincidunt, eget faucibus ex egestas. Aliquam commodo enim at lorem blandit sodales. Aenean sed tellus vitae nisl imperdiet molestie eget id mauris. Praesent non ullamcorper sapien.</p>
</div>
<div class="footer jsEq-3">
<p>Duis feugiat id nunc a maximus.</p>
</div>
</div>
<div class="column">
<div class="header jsEq-1">
<h2>Medium heading blandit id sollicitudin eget, pellentes</h2>
</div>
<div class="body jsEq-2">
<p>Pellentesque quam augue, blandit id sollicitudin eget, pellentesque in nunc. Curabitur sed purus justo. Maecenas aliquet, purus non porta vestibulum, dolor nisi congue nisi, id tincidunt quam nisi non lacus. Morbi in nunc eget neque rhoncus dapibus. Morbi id orci ligula. Duis elementum, sem eget tempus bibendum, est purus vestibulum felis, ut aliquam sem felis id massa. Aliquam non imperdiet ligula, vitae laoreet nisl. Fusce vehicula metus nec lectus luctus tempor. Integer laoreet ligula quis magna dignissim, sed convallis tellus finibus. Mauris arcu justo, dignissim congue maximus vel, faucibus eu ipsum. Duis ullamcorper mi in risus finibus fermentum. Pellentesque ut metus feugiat arcu ullamcorper elementum et sed nunc. Donec luctus diam a orci elementum, in sollicitudin mauris scelerisque. Morbi aliquet enim enim. Nullam quis pretium lectus. </p>
</div>
<div class="footer jsEq-3">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
</div>
<div class="column">
<div class="header jsEq-1">
<h2>Long heading pellentesque quam augue, blandit id sollicitudin eget, pellentesque in nunc</h2>
</div>
<div class="body jsEq-2">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas metus sapien, vulputate eget molestie eu, ultricies sit amet urna. Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
<div class="footer jsEq-3">
<p>Donec mollis pharetra tortor, nec sollicitudin ligula sodales vel. Duis feugiat id nunc a maximus.</p>
</div>
</div>