What is the best way to move an element from a relative to an absolute position smoothly?

I've been working on my portfolio site and came up with a unique idea for the landing page – having the name placed in the center and then transitioning into a navbar when a route is selected.

However, I'm facing a dilemma. To achieve this effect, I either have to position the navbar items absolutely (which I'd like to avoid) or center the name relative to its original position on the screen (also not ideal).

You can see how it currently looks here

I am using Vue with Tailwind, but would appreciate a vanilla HTML solution as well.

This is the code snippet I have:

<template>
  <header
    class="bg-black/25 py-3 transition-[max-height] duration-1000 ease-in-out max-h-screen h-screen justify-center"
    :class="{
      'flex max-h-20': !isHomePage,
    }"
  >
    <div
      class="w-5/6 flex justify-between items-center"
      :class="{ 'h-screen': isHomePage }"
    >
      <router-link to="/" :class="{ 'flex space-x-2 items-end': !isHomePage }">
        <div
          class="text-3xl font-semibold transition-all absolute duration-1000 left-1/2 top-1/3 -translate-y-4"
          :class="{
            'relative !translate-y-0 !translate-x-0 left-0 top-0': !isHomePage,
          }"
        >
          Aby
        </div>
        <div
          class="text-2xl font-medium transition-all duration-1000 absolute left-1/2 top-1/3 translate-y-4 -translate-x-4"
          :class="{
            'relative !translate-y-0 !translate-x-0 left-0 top-0': !isHomePage,
          }"
        >
          Isakov
        </div>
      </router-link>
      <router-link to="/other">click</router-link>
    </div>
  </header>
</template>

While I initially tried positioning the navbar items absolutely, it caused issues with responsiveness of the component.

Answer №1

If you want to implement a transition that alters the 'position' css property, there are several steps you need to take. Here is a function that achieves this for a relative positioned element:

function positionTransition(element) {
    var rectBefore = element.getBoundingClientRect(); //obtain old coordinates
    
    //adjust positioning:
    element.style.position = "absolute";
    element.style.left = "50vw";
    element.style.top = "50vh";
    
    var rectAfter = element.getBoundingClientRect(); //retrieve new coordinates
    
    //calculate the difference:
    var xDiff = -(rectAfter.x - rectBefore.x);
    var yDiff = -(rectAfter.y - rectBefore.y);
    
    //apply translation to simulate the element staying in its original position:
    element.style.transform = "translate(" + xDiff + "px, " + yDiff + "px)";
    
    //finally, add the transition effect with position remaining as absolute
    setTimeout(function() { //transition won't work without the timeout delay
        element.style.transition = "transform 1000ms ease-in-out";
        element.style.transform = "";
    }, 10);
}

No need to worry about any flickering effects, as the change in position and translation back happen instantaneously!

EDIT1

I have included a complete example in the following code snippet:

    window.addEventListener("DOMContentLoaded", function() {
        setTimeout(function() {
            var element = document.querySelector(".the-changing-span");
            positionTransition(element);
        }, 1000);
    });
    
    function positionTransition(element) {
        var rectBefore = element.getBoundingClientRect(); //get old coordinates
        
        //change positioning:
        element.style.position = "absolute";
        element.style.left = "50vw";
        element.style.top = "50vh";
        
        var rectAfter = element.getBoundingClientRect(); //get new coordinates
        
        //calculate the difference:
        var xDiff = -(rectAfter.x - rectBefore.x);
        var yDiff = -(rectAfter.y - rectBefore.y);
        
        //translate, so that the absolute positioned element seems to be in the old place:
        element.style.transform = "translate(" + xDiff + "px, " + yDiff + "px)";
        
        //finally, make the transition, which works because it remains in position: absolute
        setTimeout(function() {
            element.style.transition = "transform 1000ms ease-in-out";
            element.style.transform = "";
        }, 10);
    }
    .the-changing-span {
        position: relative;
    }
    
    span {
        border: 1px solid #AAA;
    }
    <span class="a-simple-span">
        stays
    </span>
    <span class="the-changing-span">
        changes
    </span>

Answer №2

Regrettably, this functionality cannot currently be implemented as per the documentation.


Source

1. w3 docs

Animated: no

2. mozilla docs

Animation type: discrete

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

The beauty of Aurelia's scoped CSS

Embarking on my Aurelia journey, I find myself navigating through the vast world of web development with tools like nodejs, gulp, and more. The Aurelia CLI has made it convenient for me to set up a visually appealing Aurelia project in Visual Studio Code ...

Minimizing the menu bar while scrolling down (bootstrap3)

Could anyone help me with creating a navigation-bar effect similar to the one seen on ? I want the bar to shrink and the logo to change after scrolling down my page. My website is built using bootstrap 3. Is there a simple way to achieve this effect with ...

"Header becomes frozen in place while scrolling, never budging from

I am looking to implement a sticky header effect on scroll, similar to the example shown here: () Check out the source site for more details: (https://github.com/davist11/jQuery-Stickem) Currently, I have a full-screen video playing at the top of the page ...

modify style when not valid and is touched

When I try to modify the style of an i tag based on the touched and invalid state of another field, only the input tag's style changes and not the i tag. Here's the CSS code I'm using: input.ng-touched.ng-invalid { border-color: red; } ...

Is there a way to position text at the bottom of a card?

Looking to showcase multiple articles on a single page? I utilized Bootstrap 5 cards to create a visually appealing layout. While everything turned out as I hoped, the only issue I'm facing is that the "read more" link is not positioned at the bottom ...

Insert content into a designated DIV

Progress bars are essential for tracking certain metrics. Take a look at the progress bars below: <div id="lifeBar-holder"> <div id="lifeBar"></div> </div> <div id="discretionBar-holder"> <div id="discretionBar"&g ...

Utilize .GLB and Blender file formats within a Gridsome project developed with Vue.js

I am working on a project using Three.js in Gridsome, but I am facing difficulties importing .glb files (3D models) with GLTFLoader. While Gridsome recognizes img (png/jpg) or .js files stored in src/assets, it does not seem to support glb files. This is ...

Tips for showcasing additional choices within a SELECT element while incorporating floating labels and adjusting the size

I'm struggling to make a floating label work smoothly with an HTML select that has a size="5" attribute using Bootstrap 5.3.x. It seems like it's not possible without some hacks or missing information from the Bootstrap documentation. According ...

Issues with integrating Angular Cypress Component tests with Tailwindcss are causing problems

While implementing Tailwindcss in an Nx style monorepo structure with 'apps' and 'libs' folders, I configured the Tailwind file as follows: content: ['./apps/**/*.{html,ts}', './libs/**/*.{html,ts}'], However, despi ...

Removing the gridlines in a Linechart using Apexcharts

I am experiencing issues with the grid and Nodata options on my Apexchart line chart. noData: { text: none , align: 'center', verticalAlign: 'middle', offsetX: 0, offsetY: 0, style: { color: undefined, fontSize: &apo ...

Is concealing content using Javascript or jQuery worth exploring?

While I have been hiding content using display:none; in css, there are concerns that Google may not like this approach. However, due to the needs of jQuery animations, it has been necessary for me. Recently, I have come across a new method for hiding conte ...

Calculating the sum in a VueJS pivot table

Currently, I am delving into VueJS and working on migrating a basic application from Laravel with the blade template engine. The backend remains unchanged, consisting of a straightforward RESTful API with 3 tables: Books, Places, and a pivot table named B ...

accordions that are supposed to adapt to different screen sizes are

My custom responsive accordions are not functioning as expected. The requirement is to display headings and content for desktop view, but switch to accordions on smaller devices. I have managed to do this, however, when resizing the window, the functionali ...

What methods can I utilize to increase the speed of my JavaScript animation?

Recently, I implemented a Vue component designed to loop a div over the X axis. While it functions correctly, I can't help but notice that it is consuming an excessive amount of CPU. I am interested in optimizing this animation for better performance. ...

Adjust the left and right margins while maintaining the vertical margin spacing

Is there a way to apply horizontal margin while inheriting vertical margin without explicitly setting margin-left and margin-right? I was hoping for something like margin: inherit 20px; to be effective. Take a look at the example here: https://jsfiddle.ne ...

Personalize Dropdown Menu, determining when to initiate the hide menu action

When creating a dropdown using ul and li tags, I am faced with the dilemma of determining the ideal time to hide the dropdown menu. The dropdown menu is designed to display values based on user input as they type, updating dynamically. Initially, I had se ...

Various web browsers (display: -webkit-inline-box;)

Recently, I encountered an issue with my CSS code: .tudo ul { width: 100%; margin: 0px; display: -webkit-inline-box; } Surprisingly, Mozilla Firefox does not recognize the following line: display: -webkit-inline-box; Is it possible to set d ...

Tips for resizing a chartjs within bootstrap columns to accommodate various web browsers

I am using chartjs charts within bootstrap rows and columns. The number of columns per row can be dynamically changed. For example, I could rebuild my rows with the following markup: const twoColumn = spacerColumn + "<div class=&ap ...

Guide to transforming the image's color with CSS3

Is there a way to transform the color of an image from grayscale to green, red, or yellow using CSS3? I attempted the code below but unfortunately, it did not produce the desired result. img { -webkit-filter: hue-rotate(90deg); filter: hue-rotat ...

A two-column layout utilizing the full height feature in Bootstrap 5, excluding the use of cards within the

I am currently attempting to create a two-column full-height page without using cards. Instead, I want to include a significant amount of text, links, and buttons in both columns. I am uncertain if this is achievable with Bootstrap columns. If anyone knows ...