Animating a Bootstrap 4 card to the center of the screen

I am attempting to achieve the following effect:

  • Display a grid of bootstrap 4 cards
  • Upon clicking a button within a card, animate it by rotating 180 degrees, adjusting its height/width from 400px - 350px to the entire screen, and positioning it at the center of the screen.

Currently, I have figured out how to implement the rotation using:

rotateY(180deg)

when the button is clicked:

$('#enlarge').on('click',
    function() {
        $('#kidCard').toggleClass("flipper");
    });

The rotation effect is set in the 'flipper' class, but I need assistance with the rest of the desired animation. Can anyone provide guidance?

Update:

Here is the current HTML code:

<div class="flip-container">
    <div class="card text-white bg-primary mb-3 kid-card" id="kidCard">
        <div class="card-header">
            Child name: ...
            <i class="fa fa-trash-o" aria-hidden="true" style="cursor: pointer"></i>
        </div>
        <div class="card-body kid-card-content">
            <div class="kid-card-content-image">
                <img src="~/Content/download.png" width="110" height="110"/>
            </div>
            <div class="kid-card-content-description">
                <p class="card-text">
                    Age: ...
                </p>
                <p class="card-text">
                    Gender: ...
                </p>
                <p class="card-text">
                    Height: ...
                </p>
                <p class="card-text">
                    Weight: ...
                </p>
            </div>
        </div>
        <div class="card-footer">
            <button class="btn btn-secondary" id="enlarge">Edit</button>
        </div>
    </div>
</div>

JavaScript file:

$('#enlarge').on('click',
    function() {
        $('#kidCard').toggleClass("flipper");
    });

Current CSS code:

.flip-container .flipper {
    transform: rotateY(180deg);
}

.flipper {
    transition: 2s;
    transform-style: preserve-3d;
    position: relative;
}

I also tried using

translateY(calc(50vh - 50%)) translateX(calc(50vh - 50%))
in the transform property to center the element on the screen, but it did not work as expected.

SOLUTION:

I was able to make it work with the following code (thanks to all for your contributions):

JS file:

$.fn.toggleZindex= function() {
            const $this = $(this);
            if($this.css("z-index")=="auto") {
                $this.css("z-index", "99999");
            }else {
                $this.css("z-index", "auto");
            }

            return this;
        };

        $.fn.animateRotate = function(angle, duration, easing, startingDegree, complete) {
            var args = $.speed(duration, easing, complete);
            var step = args.step;
            return this.each(function(i, e) {
                args.complete = $.proxy(args.complete, e);
                args.step = function(now) {
                    $.style(e, 'transform', 'rotateY(' + now + 'deg)');
                    if (step) return step.apply(e, arguments);
                };

                $({ deg: startingDegree}).animate({deg: angle}, args);
            });
        };

        function getRotationDegrees(obj) {
            const matrix = obj.css("-webkit-transform") ||
                obj.css("-moz-transform")    ||
                obj.css("-ms-transform")     ||
                obj.css("-o-transform")      ||
                obj.css("transform");
            if(matrix !== 'none') {
                const values = matrix.split('(')[1].split(')')[0].split(',');
                const a = values[0];
                const b = values[1];
                var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
            } else { var angle = 0; }
                    return (angle < 0) ? angle + 360 : angle;
        }

        $('.editChildButton').on('click',
            function () {
                const idOfChild = $(this).attr('ChildId');
                const tc = $(window).height() / 2 - $('.item').height() / 2 - $(this.closest('.item')).offset().top;
                const lc = $(window).width() / 2 - $('.item').width() / 2 - $(this.closest('.item')).offset().left;

                $(this.closest('.item')).toggleZindex();

                const startingDegree = getRotationDegrees($(this.closest('.item')));

                $(this.closest('.item')).animateRotate(startingDegree == 0 ? 180 : 0, 2000, 'swing', startingDegree);

                $(this.closest('.item')).animate({
                    left: lc,
                    top: tc
                }, 2000, function () {
                    $(this.closest('.item')).css({ position: 'fixed', left: $(this.closest('.item')).offset().left, top: $(this.closest('.item')).offset().top });
                    $(this.closest('.item')).animate({
                        left: 0,
                        top: 0,
                        width: '100vw',
                        height: '100vh'
                    },2000);
                });
            });

Answer №1

If you're looking to optimize the movement of cards, consider utilizing the position: absolute property.

When centering a div on screen, understanding the element's dimensions is crucial during transitions. If manual dimension setting is feasible, use:

left: calc(50% - manuallySetWidth);
top: calc(50% - manuallySetHeight);

If manual setting isn't an option, explore alternative methods like CSS variables which offer flexibility in positioning elements. Check out this resource for a guide on using CSS variables effectively.

The code includes comments for clarity.

//define vars for css usage
$('#kidCard')[0].style.setProperty('--width', $('#kidCard').width()+'px');
$('#kidCard')[0].style.setProperty('--height', $('#kidCard').height()+'px');

$('#enlarge').on('click',
  function() {
    $('#kidCard').toggleClass("flipper");
    $('body').toggleClass("shady");
});
body{
  transition: 1s;
}

body.shady{
  background: rgba(0,0,0,.8);
  
}

.flip-container .card {
  left: 0;/*manually set each card's left and top in order for the translation to work smoothly, */
  top: 0;/*if you have them in a grid you could use i and j to do this */
  text-align: center;
  border: 1px solid red;
  transition: 1s;
  position: absolute;
  background: white;
}

.flip-container .card.flipper {
  transform: rotateY(360deg);
  left: calc(50% - var(--width)/2); /*use the variables set in js*/
  top: calc(50% - var(--height)/2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="flip-container">
<div class="card text-white bg-primary mb-3 kid-card" id="kidCard">
<div class="card-header">
Child name: ...
<i class="fa fa-trash-o" aria-hidden="true" style="cursor: pointer"></i>
</div>
<div class="card-body kid-card-content">
<div class="kid-card-content-image">
<img src="~/Content/download.png" width="110" height="110"/>
</div>
<div class="kid-card-content-description">
<p class="card-text">
Age: ...
</p>
<p class="card-text">
Gender: ...
</p>
<p class="card-text">
Height: ...
</p>
<p class="card-text">
Weight: ...
</p>
</div>
</div>
<div class="card-footer">
<button class="btn btn-secondary" id="enlarge">Edit</button>
</div>
</div>
</div>

Answer №2

I believe that achieving a specific effect may require more than just CSS animations. One approach could be to adjust the positioning to fixed, center the card, and scale it according to your needs. You can see a demonstration here.

While the example provided is for a single card, it should also work with multiple cards in different positions. When clicking on the card:

  1. It rotates 180 degrees (although the reason for this exact rotation is unclear),
  2. Moves to the center of the viewport,
  3. Changes size to occupy the entire viewport.

The animation functions bidirectionally.

HTML:

<div class="flip-container">
    <div class="card text-white bg-primary mb-3 kid-card" id="kidCard">
        <div class="card-header">
            Child name: ...
            <i class="fa fa-trash-o" aria-hidden="true" style="cursor: pointer"></i>
        </div>
        <div class="card-body kid-card-content">
            <div class="kid-card-content-image">
                <img src="~/Content/download.png" width="110" height="110"/>
            </div>
            <div class="kid-card-content-description">
                <p class="card-text">
                    Age: ...
                </p>
                <p class="card-text">
                    Gender: ...
                </p>
                <p class="card-text">
                    Height: ...
                </p>
                <p class="card-text">
                    Weight: ...
                </p>
            </div>
        </div>
        <div class="card-footer">
            <button class="btn btn-secondary" id="enlarge">Edit</button>
        </div>
    </div>
</div>

CSS:

.flip-container {
  width: 400px;
}

.flip-container .flipper {
    transform: rotateY(180deg);
}

.card {
  transition-duration: 2s;
}

.movement {
  transform: translate(-50%,-50%) rotateY(180deg);
}

JS:

var element = $('#kidCard');
var w = element.width();
var h = element.height();

$('#enlarge').on('click',
  function() {
    if(element.hasClass('movement')) {
      element.removeClass('movement');
      element.css({width: w, height: h, top: 0, left: 0});
    } else {
      var left = element.offset().left;
      var top = element.offset().top;
      element.css({position: 'fixed', left: left, top: top, width: w, height: h});
      element.addClass('movement');
      element.css({width: '100vw', height: '100vh', top: '50%', left: '50%'});
   }
});

Answer №3

To center a block level element, one approach is to specify a width for your flipper class and set the margins to auto. By setting both a width value and margin:auto, you can achieve center alignment.

.flip-container .flipper {
    transform: rotateY(180deg);
}

.flipper {
    transition: 2s;
    margin: auto;
    width:400px;
    height:400px;
    transform-style: preserve-3d;
    position: relative;
}

Here is a fiddle

Alternatively, if you prefer a flexbox solution, you can use the following code:

.flip-container .flipper {
    transform: rotateY(180deg);
}

.flipper {
    transition: 2s;
    transform-style: preserve-3d;
    position: relative;
    width:400px;
    height:400px;
}

.body-flipper {
  display:flex;
  justify-content: center;
}

body, html{
  width:100% !important;
  height: 100% !important;
  margin:0;
}

Here is a fiddle

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

Authentication Error (401) in WordPress JWT

Recently, I came across WordPress and started using it. However, I encountered some issues while trying to integrate JWT with a custom endpoint. Despite configuring my API and JWT correctly, I faced an authentication problem during my AJAX request. It&ap ...

Transferring Data to EJS Template

I have been facing a challenge in passing a value from a POST route to an EJS file for display. Despite trying various methods like redirecting, sending, and rendering the results, the data won't make its way to the EJS file. Below is the POST route ...

Tips for expanding third-party classes in a versatile manner using Typescript

tl;dr: Seeking a better way to extend 3rd-party lib's class in JavaScript. Imagine having a library that defines a basic entity called Animal: class Animal { type: string; } Now, you want to create specific instances like a dog and a cat: const ...

To subscribe to the display of [Object Object], you cannot use an *ngIf statement without being inside an *ngFor loop

In my angular Quiz project, I have a functionality where every user can create quizzes. I want to display all the quizzes that a logged-in user has completed. Here is how I attempted to achieve this: // Retrieving user ID and category ID inside Re ...

Styling on a device can vary from how it appears on a

Using Ionic2, I have an application with messages. In a browser, the message appears like this: https://i.stack.imgur.com/SyCtM.png However, when running on either an Android or iOS device, it looks different: https://i.stack.imgur.com/i0RdO.png The di ...

`Slide bootstrap carousel without moving other elements`

.carousel { position: relative; height: 500px; .carousel-inner .item { height: 500px; } .carousel-indicators > li { margin: 0 2px; background-color: $maincolor; border-color: $maincolor; opacity: .7; ...

Issue with Scrollspy Functionality in Bootstrap 4

Scrollspy feature isn't working in my code. <nav class="navbar navbar-expand-lg fixed-top navbar-dark" role="navigation"> <div class="container"> <a class="navbar-brand" href="#featured"><h1></h1></a> < ...

Can a Unicode character be overwritten using a specific method?

Is there a way to display a number on top of the unicode character '♤' without using images? I have over 200 ♤ symbols each with a unique number, and using images would take up too much space. The characters will need to be different sizes, a ...

Utilize middleware in a separate controller file to handle specific tasks within an Express application

Currently, I have implemented a code snippet that utilizes the express-fileupload middleware for file uploads: const fileUpload = require('express-fileupload'); app.use(fileUpload({useTempFiles: true})); app.post('/upload', (req, re ...

Mastering the control of a camera in three.js using a combination of keyboard and mouse navigation techniques

I have been working on a 3D environment in WEB GL using three.js, previously using orbitcontrols.js as shown in this project: http://codepen.io/nireno/pen/cAoGI. Recently, I came across a different method of navigating the environment using the W, A, S, D ...

Utilize typehead.js in Python Django to retrieve an updated data list directly from the database

file.js var source = new Bloodhound({ hint: false, datumTokenizer: Bloodhound.tokenizers.obj.whitespace("description"), queryTokenizer: Bloodhound.tokenizers.whitespace, // /a_c/p_s/?term=d&category=all remote: "/a ...

Which is better for testing in Cypress: classes or functions?

When it comes to testing in Cypress, which approach do you believe is more efficient? Functions: 'support/pages/login.js' export const login = (username, password) => { cy.get('#username').type(username); cy.get(& ...

Arranging card images in a row using semantic cards for optimal alignment

Trying to create a row of semantic-ui cards with images at the top, I ran into an issue with varying image heights causing different card title positions. The goal is to have all images be the same height while still adapting to larger screens. Although I ...

display rails view using ajax

I have developed a new form that I would like to render using ajax in case it fails validations. In my controller, the code looks like this: def create event = CEvent.new(params[:c_event]) respond_to do |format| if event.save format.html { ...

Customizing data attributes for child components in Vue 2

In my Vue project, I have created a multi-page questionnaire using the v-show directive within a container called RiskAssessmentTest.vue. To handle loading questionnaire drafts, I have a component named RiskAssessmentDrafts.vue, which has the following st ...

Retrieve the URL with a GET request and remove a specific object

Currently, I am working on developing a CRUD (Create, Read, Update, Delete) App using Express and LowDB. So far, I have successfully implemented the create and read functions, but I am facing issues with the delete function. This is an example of what th ...

Set the value of a variable to the result of a JavaScript function

I recently wrote a function that retrieves JSON data from a specified URL. Here's what the function looks like: function getJSON(url) { request.get({ url: url, json: true, headers: { 'User-Agent': 'request&a ...

Is the strange z-index behavior causing issues with mouse interactions a bug or a standard occurrence?

Whenever I attempt to adjust the z-index on my webpage to rearrange the layering of overlapping divs, I always encounter an issue where the lower div becomes unresponsive to mouse events. Currently, my setup includes: <div class="leftcolumn"> <d ...

Waiting for the result of an AngularJS promise

When I click a button in my AngularJS app, the following code is executed: if (!$scope.isChecked) { $scope.getExistingName($scope.userName).then(function (data) { $scope.userName = data; }); } // Additional processing code foll ...

Tips for refreshing the page without losing the values of variables

In my simulation.jsp file, I have the following code that retrieves simulation data from a struts2 action: $(document).ready(function() { var data='<s:property escape="false" value="simInfos" />'; } Once I perform the simulation with this ...