When you traverse the DOM and modify the CSS, why does the style of the subsequent element become the style of the first element?

cause

at present, I want to do a drag-and-drop sorting and drawing function. After consideration and reference, it is found that most of the solutions are to change the elements to absolute positioning, and then interpolate left and top, through transition or other ways, so this way is tested.

question

but a problem was found in the coding. When you use js or jQuery to traverse and modify the element css, all elements are assigned the CSS style of the first element.
when you do not modify CSS, the printed css variables are normal, but if you change them, all subsequent variable values become the values of the first time.
I don"t know why this problem is caused and how to solve it.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            box-sizing: border-box;
        }

        .container {
            display: flex;
            width: 100%;
            flex-wrap: wrap;
            position: relative;
        }

        .box {
            flex: 0 0 25%;
            border: 1px solid -sharp999;
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="box" draggable="true">1</div>
        <div class="box" draggable="true">2</div>
        <div class="box" draggable="true">3</div>
        <div class="box" draggable="true">4</div>
        <div class="box" draggable="true">5</div>
        <div class="box" draggable="true">6</div>
        <div class="box" draggable="true">7</div>
        <div class="box" draggable="true">8</div>
        <div class="box" draggable="true">9</div>
        <div class="box" draggable="true">10</div>
        <div class="box" draggable="true">11</div>
        <div class="box" draggable="true">12</div>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script>
        $(document).ready(function () {
            $(".box").each(function () {
                var css = {
                    "position": "absolute",
                    "left": $(this)[0].offsetLeft,
                    "top": $(this)[0].offsetTop,
                    "width": $(this)[0].offsetWidth,
                    "height": $(this)[0].offsetHeight
                };
                console.log(css);
                $(this).removeClass("box");
                //  css 
                // position:absolute;left: 0px; top: 10px;width: 226px;height: 23px
                $(this).css(css);
            });
        });
    </script>
</body>

</html>

causes and solutions

A few days later I reviewed the issue and reorganized my final understanding.

the focus of this problem is that the css () method of jQuery or javascript modifies style will trigger rearrangement immediately .

After

modifies css and removes box , the browser has immediately moved the second item to the location of the first item.

rearrangement is triggered every time css is modified, so the solution is to change the style after fetching all the css data (at the end of the loop).
that is:

$(".box").each(function () {
    var css = {
        "position": "absolute",
        "left": $(this)[0].offsetLeft,
        "top": $(this)[0].offsetTop,
        "width": $(this)[0].offsetWidth,
        "height": $(this)[0].offsetHeight
    };
    var that = $(this);
    setTimeout(function () {
        that.css(css);
        that.removeClass("box");
    }, 0);
});
Mar.22,2021

execute $(this) .css (css); after this, your $(this) [0] .offsetLeft, these have all changed


you have 10 boxes that are tired, and you decide to pull the last one to stick it to the wall, and then the other nine fall off, so the position of the last box you get is always the same every time, because they are always at the bottom of .

the solution is not to pull out the last box immediately, but to perform the extraction operation after measuring all the dimensions.

function queueUpdate($el, css) {
  setTimeout(function () {
    $el.css(css)
  }, 0)
}

$(document).ready(function () {
  $('.box').each(function () {
    var css = {
      'position': 'absolute',
      'left': $(this)[0].offsetLeft,
      'top': $(this)[0].offsetTop,
      'width': $(this)[0].offsetWidth,
      'height': $(this)[0].offsetHeight
    };
    $(this).removeClass('box');
    
    //  css 
    // position:absolute;left: 0px; top: 10px;width: 226px;height: 23px
    queueUpdate($(this), css)
  });
});
Menu