Home > Enterprise >  I am creating css flip cards for projects using Django template tags to iterate over the cards. All
I am creating css flip cards for projects using Django template tags to iterate over the cards. All

Time:10-14

As it says in the title. I know Django well, but am still getting the hang of using JS for this type of thing. I am iterating over the cards with {% for project in projects %}, and everything is showing up as it should. And, when I click the button on the first card, it flips the card perfectly. However, when I click the button of any other card, they also flip the first card as well, instead of flipping the next card itself. I think it has something to do with the id of the divs or labels, and have tried a few things but I haven't quite figured it out.

Here is the necessary HTML:

 <div class="wrapper">
                    {% for project in projects %}
                        <div class="card">
                            <input type="checkbox" id="card1" class="more" aria-hidden="true">
                            <div class="content">
                                <div class="front"
                                     style="background-image: url({{ project.image }})">
                                    <div class="inner">
                                        <h2>{{ project.title}}</h2>

                                        <label for="card1" class="button" aria-hidden="true">
                                            Details
                                        </label>
                                    </div>
                                </div>
                                <div class="back">
                                    <div class="inner">
                                        <div class="info">

                                        </div>
                                        <div class="description">
                                            <p>{{ project.description }}</p>

                                        </div>
                                        <div class="location">Warsaw, Poland</div>
                                        <div class="price">38€ / day</div>
                                        <label for="card1" class="button return" aria-hidden="true">
                                            <i class="fas fa-arrow-left"></i>
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </div>
                    {% endfor %}

The CSS pertaining to the cards:

    <style>

        .wrapper {
            display: flex;
            flex-flow: row wrap;
            justify-content: center;
        }

        .card {
            width: 420px;
            height: 340px;
            margin: 1em;
            perspective: 1500px;
        }

        .card .content {
            position: relative;
            width: 100%;
            height: 100%;
            transform-style: preserve-3d;
            transition: transform 0.8s cubic-bezier(0.75, 0, 0.85, 1);
        }


        .more:checked ~ .content {
            transform: rotateY(180deg);
        }

        .front,
        .back {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            backface-visibility: hidden;
            transform-style: preserve-3d;
            border-radius: 6px;
        }

        .front .inner,
        .back .inner {
            height: 100%;
            display: grid;
            padding: 1.5em;
            transform: translateZ(90px) scale(0.75);
        }

        .front {
            background-color: #fff;
            background-size: cover;
            background-position: center center;
        }

        .front:after {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: block;
            border-radius: 6px;
            backface-visibility: hidden;
            background-image: url("{{ project.image }}");

        }

        .front .inner {
            grid-template-rows: 5fr 1fr 1fr 2fr 1fr;
            justify-items: center;
        }

        .front h2 {
            grid-row: 2;
            margin-bottom: 0.3em;
            text-transform: uppercase;
            letter-spacing: 3px;
            color: #fff;
            font-weight: 500;
            text-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
        }

        .front .rating i {
            margin: 0 1px;
        }

        .back {
            transform: rotateY(180deg);
            background-color: #fff;
            border: 2px solid #f0f0f0;
        }

        .back .inner {
            grid-template-rows: 1fr 2fr 1fr 2fr 14fr 1fr 1fr;
            grid-template-columns: repeat(3, auto);
            grid-column-gap: 0.8em;
            justify-items: center;
        }

        .back .info {
            position: relative;
            display: flex;
            align-items: center;
            color: #355cc9;
            grid-row: 3;
        }

        .back .info:not(:first-of-type):before {
            content: "";
            position: absolute;
            left: -0.9em;
            height: 18px;
            width: 1px;
            background-color: #ccc;
        }

        .back .info span {
            font-size: 2em;
            font-weight: 700;
        }

        .back .info i {
            font-size: 1.2em;
        }

        .back .info i:before {
            background: linear-gradient(40deg, #355cc9, #438af3);
            -webkit-text-fill-color: transparent;
            -webkit-background-clip: text;
        }

        .back .info .icon {
            margin-left: 0.3em;
        }

        .back .info .icon span {
            display: block;
            margin-top: -0.25em;
            font-size: 0.8em;
            font-weight: 600;
            white-space: nowrap;
        }

        .back .description {
            grid-row: 5;
            grid-column: 1/-1;
            font-size: 0.86em;
            border-radius: 5px;
            font-weight: 600;
            line-height: 1.4em;
            overflow: auto;
            color: #355cc9;
            padding-right: 10px;
        }

        .back .location,
        .back .price {
            font-weight: 600;
            color: #355cc9;
            grid-row: 1;
            font-size: 0.86em;
        }

        .back .location {
            grid-column: 1/3;
            justify-self: left;
        }

        .back .price {
            grid-column: 3/-1;
            justify-self: right;
        }

        .back .button {
            grid-column: 1/-1;
            justify-self: center;
        }

        .button {
            grid-row: -1;
            text-transform: uppercase;
            letter-spacing: 1px;
            font-weight: 600;
            cursor: pointer;
            display: block;
            padding: 0 1.5em;
            height: 3em;
            line-height: 2.9em;
            min-width: 3em;
            background-color: transparent;
            border: solid 2px #fff;
            color: #fff;
            border-radius: 4px;
            text-align: center;
            left: 50%;
            backface-visibility: hidden;
            transition: 0.3s ease-in-out;
            text-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
        }

        .button:hover {
            background-color: #fff;
            box-shadow: 0 0 50px rgba(0, 0, 0, 0.5);
            text-shadow: none;
            color: #355cc9;
        }

        .button.return {
            line-height: 3em;
            color: #355cc9;
            border-color: #355cc9;
            text-shadow: none;
        }

        .button.return:hover {
            background-color: #355cc9;
            color: #fff;
            box-shadow: none;
        }

        ::-webkit-scrollbar {
            width: 5px;
        }

        ::-webkit-scrollbar-track {
            background: #f1f1f1;
        }

        ::-webkit-scrollbar-thumb {
            background: #859ddf;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: #355cc9;
        }
    </style>

And the javascript (I had a different jquery script at one point but this is what I've got now:

        (function () {
            var tab = document.querySelector('.card');

            document.getElementById('card1').addEventListener('click', function () {
                tab.classList.add('back');
            }, false);

            document.getElementById('card1').addEventListener('click', function () {
                tab.classList.remove('front');
            }, false);

        })();
    </script>

I'm not sure if anything else would be helpful, but if anybody has a good idea of what may be going on it would be incredibly helpful. This is the only snag I've hit where I've had to ask a question for my last few projects. It's just annoying. Thanks.

CodePudding user response:

The reason why all buttons only flip the first card is just because your id is hardcoded with "card1", the id's value on html should be unique. The "card1" id is only targetting the first element that use the same id

<input type="checkbox" id="card1" class="more" aria-hidden="true">

You should generate dynamic id for each iteration, so for example you could generate the ids value with "card1", "card2", "card3", etc.

Same with the js

 document.getElementById('card1').addEventListener('click', function () {
            tab.classList.add('back');
        }, false);

        document.getElementById('card1').addEventListener('click', function () {
            tab.classList.remove('front');
        }, false);

You should create dynamic event listener for each id

See how the html id works on HTML id

CodePudding user response:

So, after Dhia Aziz Rizqi confirmed my suspicion that it was, in fact, the ID that was the issue; and there wasn't any other underlying issue,I immediately went to try and dynamically call the project ID with Django inside the JS function. It worked perfectly.

I hadn't used Django template tags inside of a JS function before, so I wasn't sure how it would go, but for anyone else who happens to come across this issue...

The javascript needed to change to this:

    <script>
        (function () {
            var tab = document.querySelector('.card');

            document.getElementById('{{ project.id }}').addEventListener('click', function () {
                tab.classList.add('back');
            }, false);

            document.getElementById('{{ project.id }}').addEventListener('click', function () {
                tab.classList.remove('front');
            }, false);

        })();
    </script>

And the HTML to this:

 <div class="wrapper">
                    {% for project in projects %}
                        <div class="card">
                            <label for="{{ project.id }}"></label><input type="checkbox" id="{{ project.id }}" class="more" aria-hidden="true">
                            <div class="content">
                                <div class="front"
                                     style="background-image: url({{ project.image }})">
                                    <div class="inner">
                                        <h2>{{ project.title}}</h2>

                                        <label for="{{ project.id }}" class="button" aria-hidden="true">
                                            Details
                                        </label>
                                    </div>
                                </div>
                                <div class="back">
                                    <div class="inner">
                                        <div class="info">

                                        </div>
                                        <div class="description">
                                            <p>{{ project.description }}</p>

                                        </div>
                                        <div class="location">Warsaw, Poland</div>
                                        <div class="price">38€ / day</div>
                                        <label for="{{ project.id }}" class="button return" aria-hidden="true">
                                            <i class="fas fa-arrow-left"></i>
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </div>
                    {% endfor %}

The solution was to simply add the project ID dynamically in place of a fixed ID.

It works wonderfully with Django.

  • Related