What is the best way to implement CSS modifications in a specific sequence?

There are times when I need to apply multiple CSS changes in a row, ensuring that each one is properly rendered.

Check out this simple example

The height of the element is set to auto, so transitioning is not possible. To work around this, I want to first set the height to its current computed value and then change the class immediately to trigger the transition. However, doing this in sequential lines of code doesn't give the renderer enough time to process each change individually.

var foo = $(".foo");
foo[0].addEventListener("click", function(ev){
  foo.css({"height":foo.height()+"px"});
  foo.addClass("active");
});  //the 'foo.css...' line is ignored.

We can use window.requestAnimationFrame() to delay actions to the smallest animatable timestep, but for Firefox compatibility, it requires nested calls.

var dan = $(".dan");
dan[0].addEventListener("click", function(ev){
  window.requestAnimationFrame(function(){
    dan.css({"height":dan.height()+"px"});
    window.requestAnimationFrame(function(){
      dan.addClass("active");
    });
  });
});  //this method works, but seems somewhat convoluted with all the nesting.

While this approach technically functions, I'm curious if there are more efficient ways to chain CSS changes like this.

Answer №1

Utilizing setTimeout in this scenario ensures that the class change occurs only after the calculation of the div's height.

For instance:

var foo = document.getElementsByClassName('foo')[0];
var bar = document.getElementsByClassName('bar')[0];
var dan = document.getElementsByClassName('dan')[0];

function fooFunction(element) {
    element.style.height = element.clientHeight + 'px';

    setTimeout(function(){
        element.classList.add('active');
        element.removeAttribute('style');
    },10);

}

foo.addEventListener('click',function(){fooFunction(foo);},false);
bar.addEventListener('click',function(){fooFunction(bar);},false);
dan.addEventListener('click',function(){fooFunction(dan);},false);
.foo, .bar, .dan{
width:20%;
display: inline-block;
overflow: hidden;
vertical-align:top;
transition: height 1s ease-out;
}

.active {
height:50px;
}

.foo {
background:rgb(150, 100, 100);
}

.bar {
background:rgb(150, 150, 100);
}

.dan {
background:rgb(100, 150, 100);
}
<div class="foo">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>

<div class="bar">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fourth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>

<div class="dan">
<p>Works.</p>
<p>Another paragraph.</p>
<p>Third paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fourth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
<p>Fifth paragraph. This one is even longer. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam, fugiat facere? Animi, odit et tempore debitis modi quae eaque, libero, dolores magni, voluptas tenetur tempora quidem alias ut praesentium sed.</p>
</div>

Answer №2

If you are unsure of the height of the target elements before the click event, you can easily check it after the DOM has loaded and then set each target element to its own height. This approach ensures that when a target element is clicked: *the animation will function smoothly as the element's height is pre-set. *there will be one less command to execute during the click event.

If you are already familiar with jQuery, you can utilize it throughout:

$(document).ready(function(){
  var $tran = $('.transition');
    $tran.each(function(){
        var height = $(this).height();
        $(this).height(height);
    });
    $tran.click(function(){
        $(this).addClass('active');
    });
});

For vanilla JavaScript:

document.addEventListener('DOMContentLoaded',function(){
  var tran = document.getElementsByClassName('transition');
  for (let i=0; i<=tran.length-1; i++){
    let height = tran[i].clientHeight;
    tran[i].style.height = height + 'px';
    tran[i].addEventListener("click", function(ev){
      this.className = this.className + " active";
    });
  }
});   

Here's an example where each target element has the 'transition' class:

<div class="foo transition">
...
<div class="bar transition">
...  
<div class="dan transition">
... 

The transition effects have been placed in their own class so they can be easily removed from the HTML later or used on other elements without being tied directly to the click event. You can achieve an "opening up" animation by toggling the classes instead of just adding them:

.foo, .bar, .dan {
  width: 20%;
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}
.transition {
  -webkit-transition: height 1000ms;
  transition: height 1000ms;
}
.active {
  height: 50px !important;
}

Live example available here. *You can choose between using pure JS or jQuery in the example by setting the "use_jquery" variable to true or false.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React - z-index issue persists

My React App with Autocomplete feature is almost complete, but I need some assistance to double-check my code. https://i.stack.imgur.com/dhmck.png In the code snippet below, I have added a search box with the className "autocomplete" style. The issue I a ...

Obtaining weather information for a particular date through wunderground

Today marks my first experience using this wunderground service. My goal is to retrieve weather data under the following circumstances: Note : Today Date :2014-02-03 I am looking to access weather data ranging from 2014-01-21 to 2014-01-31, which fal ...

Using Angular to invoke the transclude directive function inside the transcluded component

I am looking to develop a component that includes a transcluded section, take a look at this example: http://jsfiddle.net/vp2dnj65/1/ Upon clicking the "do" button in the example, nothing seems to happen. Is there a way to execute the transcluded cont ...

CSS menu - Shifting bar: What's the issue?

I'm struggling to add a moving bar to my website's navigation and need some help. I tried following a tutorial at the following link: (http://css-tricks.com/jquery-magicline-navigation/) Here is what I ended up with: If anyone could take a look ...

Loop through a collection of items based on the values in a separate array using jQuery

I have a list of objects below The newlist and SelectID array are both dynamic. I am populating through a function, now I need to iterate and create the new list. var newList = [ { id : 1,name="tea",plant:"darjeeling"}, { id : 2,name="cof ...

Adjusting Classes in JavaScript with jQuery

I need to create a feature that changes the state of a button from active to inactive based on user input, using Bootstrap. Ultimately, I am working towards finding an intuitive way to validate form input so that the submit button can be pressed for PHP pr ...

invoking both componentDidMount and componentDidUpdate within the identical code block

componentLifeCycleMethod() { let data ; axios.get('http://localhost:8000/wel/') .then(res => { data = res.data; this.setState( { details: data }); }) .catch(err => {}) } I am looking to opt ...

Transferring an IONIC project to a different computer

Let me outline the current situation I am facing - I primarily work as a firmware developer rather than a software developer. Recently, a team member who was responsible for developing the front end of an application in IONIC has left the company, leaving ...

What is the best method for transferring formatted text from the clipboard to an HTML textarea?

When you copy and paste from a web browser to a text processor, the HTML markup gets converted to rich text. The text processor then tries to convert this markup into its own format, proving that the Clipboard can hold markup. However, when you copy and p ...

Spinning objects in three.js using tween.js to move around the global axis

Currently, I am working on tween-rotating a 3D cube. Thanks to this helpful post (How to rotate a object on axis world three.js?), I have successfully achieved rotation without any issues. Now, my goal is to transfer the rotation achieved through setFromRo ...

Utilizing ag-grid in React to render boolean values as text instead of checkboxes

When working with AG-Grid-react, is there a way to show boolean values as text in a column instead of checkboxes by default? I need help finding a property that can achieve this. ...

Styling with CSS: How to Show an Absolutely Positioned Element in Google Chrome

I'm currently working on a CSS design that involves positioning an image within a span tag. Here's the CSS code I have: .dc-mega-icon { background-image: url(...); display: inline-block; position: absolute; top: 18px; width: ...

While developing my project in NextJS, I encountered a frustrating issue where the build process would fail consistently, even though the development environment ran smoothly. The

Hello everyone, I'm a beginner posting here for the first time. I am still getting the hang of React and JavaScript in general, and currently working on a project in NextJS. It's interesting to note that my project runs smoothly when I use next d ...

What can be done to stop the caching of the route that router.push() redirects to in Next.js middleware?

Encountering an issue with client-side navigation and middleware in the router. It seems that the router is storing the initial redirect path and subsequent navigations bypass the middleware. This behavior ceases upon browser refresh and does not occur in ...

Use jQuery's animate function to toggle a different div when clicking on one

Having trouble with a jQuery function that keeps triggering the second function every time I click. How can I fix this issue? I designed a navbar with 3 links, each linked to a different .contentDiv with unique IDs. Whenever a link is clicked, a toggle fu ...

Using Firebase to connect and disconnect from state in React with Re-base

I'm encountering some issues with React and Firebase while using the re-base module. When attempting to retrieve content from Firebase across different components in my app, I run into a problem. On one component/"page," which is home, I have the abi ...

What is the maximum character limit for jQuery?

Here's a code snippet I'm working with: $.get("url") .done(function(data){ alert("success"); alert(JSON.stringify(data)); }) .fail(function(data){ alert("fail"); alert(JSON. ...

Retrieving status code without reliance on a back-end language (maybe through JavaScript?)

My new service offers a solution for error pages in web apps by providing a code snippet that can be easily copied and pasted into the error page templates, similar to Google Analytics. The status code is embedded in a hidden input within the installatio ...

Establish a dynamic video backdrop for Bootstrap's Jumbotron element

Is there a way to set a video as the background of this jumbotron and ensure that it fills the entire space while still being responsive? Link to Bootstrap documentation on jumbotron <div class="jumbotron"> <div class="container"> <h ...

Guide on adding a post type via the command line: Issue encountered - Anticipated POST console HTML error

Facing Error: EXPECTED POST in JQuery Ajax Call Encountering the same issue as mentioned in the provided link. The need is to switch from GET to POST, but direct alteration of ajax code is not feasible. It must be done dynamically using JavaScript through ...