How to prevent table row height glitch during DOM append?

Viewed 255

I load my table first, then I dynamically append tags asynchronously. As soon as those tags are appended, the table row height seems to shift up. How can I prevent that ?

enter image description here

I've tried

.portfolio-table tr {
    height: 80px;
}

Table

<table class="table portfolio-table">
    <thead class="thin-border-bottom">
        <th width="2%">#</th>
        <th width="28%">Name</th>
        <th width="60%" class="text-left">Tags</th>
        <th width="5%">Edit</th>
        <th width="5%">Delete</th>
    </thead>

    <tbody>

        <tr>

            @foreach ($portfolios as $portfolio)
            <td title="{{ $portfolio->id }}">{{ $portfolio->id }} </td>

            <td>
                <a href="/portfolio/{{ $portfolio->id ?? '' }}/">
                    {{ $portfolio->name }}
                </a>
            </td>

            <td class="text-right" >
                <img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px">
                <p class="portfolioSkillTags text-left" id="{{ $portfolio->id ?? '' }}"></p>

            </td>


            <td>
                <a  href="/portfolio/{{ $portfolio->id ?? '' }}/edit" type="button" class="btn btn-info btn-sm">
                    Edit
                </a>
            </td>

            <td>
                <a  data-toggle="modal"  data-target="#delete_portfolio_{{ $portfolio->id ?? '' }}" type="button" class="btn btn-danger btn-sm">
                    Delete
                </a>
            </td>

        </tr>

        @endforeach

    </tbody>
</table>

ajax

$("tbody").each(function(){
    $($(this)).find('tr').each(function(){

        var selector = $(this);
        var id = $(this).find('td:nth-child(1) ').attr('title');
        // console.log('%c id = ' + id, "color: green;");
        // return false;
        var data = {};
        data.id  = id;

        $.ajax({
            method: 'POST',
            url: '/api/portfolio/' + id + '/skills',
            crossDomain: true,
            contentType: false,
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('value'),
                "Accept": "application/json",
                "Content-Type": "application/x-www-form-urlencoded",
                "Cache-Control": "no-cache"
            },
            data: data,
            success: function(response){
                console.log(id, response);

                $('p.portfolioSkillTags#'+ id).prev('img').fadeOut();

                for (i = 0; i < response.length; i++) {
                    // console.log(response[i],id);

                    var name  = response[i]['name'];
                    var color = response[i]['color'];

                    $('p.portfolioSkillTags#'+id).prepend('<span class="badge" style="background-color:' + hexToRgb(color,.2) + ';border:' + hexToRgb(color,.7) + ' 2px solid;">' + name + '</span>').fadeIn('slow');
                }

            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log(JSON.stringify(jqXHR));
                console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
            }
        });



    });
});
4 Answers

It seems the loading spinner image causes the glitch since it makes the

text oveerflow. You can try fix it with some css style like float right so it wont make the paragraph wrap.

<img src="/assets/fe/img/svg/default.svg" style="float: right;" alt="Loading" width="30px">

The issue is with the height of the spinner (svg element). When you loads the data asynchronously, it brings the spinner with larger height. As soon as your API call resolves successfully, the spinner element (which has larger height goes away). Then your other data that can be retained in less height shrinks and produces this issue.

You can fix it with many ways, the simplest one is, keep the height(including paddings) of spinner (svg) element smaller than height of td element. For example:

<img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px" height="30px">


.portfolio-table tr td {
    height: 50px;
}

UODATE

Please rectify the HTML as well, you might want to start the foreach loop outside the start tag of tr HTML element.

@foreach ($portfolios as $portfolio)
<tr>

            <td title="{{ $portfolio->id }}">{{ $portfolio->id }} </td>

            <td>
                <a href="/portfolio/{{ $portfolio->id ?? '' }}/">
                    {{ $portfolio->name }}
                </a>
            </td>

            <td class="text-right" >
                <img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px">
                <p class="portfolioSkillTags text-left" id="{{ $portfolio->id ?? '' }}"></p>

            </td>


            <td>
                <a  href="/portfolio/{{ $portfolio->id ?? '' }}/edit" type="button" class="btn btn-info btn-sm">
                    Edit
                </a>
            </td>

            <td>
                <a  data-toggle="modal"  data-target="#delete_portfolio_{{ $portfolio->id ?? '' }}" type="button" class="btn btn-danger btn-sm">
                    Delete
                </a>
            </td>

        </tr>

        @endforeach
$('p.portfolioSkillTags#'+ id).prev('img').fadeOut();

make this to

$('p.portfolioSkillTags#'+ id).prev('img').hide();

and Please rectify the HTML as well, you might want to start the foreach loop outside the start tag of tr HTML element as mentioned by Prince

I think the problem is a css animation. Try something to globally enforce to disable them to see if the behavior disappear.

* {
    animation: none !important;
}

If that is the case disable the animation with the right css selector when you are loading your data.

Related