Display a floating label above the text input when it is focused or when it holds text

I am trying to create an animated search bar where the label moves from being over the text input to above it. I came across a helpful example in a fireship.io video, which includes the CSS and HTML code available here

The example I found demonstrates the behavior and style I want, with the label moving above and staying there when text is entered, similar to Material UI.

However, when I implement it, I only get half of the desired behavior - the label moves when I focus on the text input but then moves back regardless of entering text:

https://i.stack.imgur.com/q4pu4.jpg

https://i.stack.imgur.com/g0GXq.jpg

https://i.stack.imgur.com/xDcPB.jpg

Below is the specific HTML and CSS code I am using within a React App and SCSS file compiled using VSCode's Live SASS Watcher extension:

function searchBar() {
    return (
        <div class="SearchBar">
            <input type="text" name="Search" class="input" placeholder=""/>
            <label class="label" for="Search">Search...</label>
      </div>
    )
}



.SearchBar {
    @extend .base;
    flex-direction: column;
    position: relative;
    border-bottom: 2px dashed var(--text-primary);
    width: 50vw;
    margin: 3vh auto 3vh;
    .input {
        border: none;
        outline: none;
        overflow: hidden;
        justify-content: center;
        align-content: center;
        padding: 1rem;
        background: none;
        color: var(--text-primary);
        letter-spacing: normal;
        text-transform: none;
        font-size: 2rem;
        font-weight: bold;
        z-index: 2;
        width: 75vw;
    }
    .label {
        color: var(--text-primary);
        z-index: 1;
        position: absolute;
        transform-origin: 0%;
        transition: transform 400ms;
    }
}

.SearchBar::after {
    content: "";
    position: relative;
    display: block;
    height: 4px;
    width: 50vw;
    background: #1625ff;
    transform: scaleX(0);
    transform-origin: 0%;
    transition: transform 500ms ease;
    top: 2px;
}

.SearchBar:focus-within {
    border-color: transparent;
    .label, .input:not(:placeholder-shown) + .label {
        transform: scale(0.8) translateY(-5rem);    
    }
}

I have tried various fixes suggested in StackOverflow and other platforms without success. For instance, adding the "required" attribute did not yield the desired outcome:

<input type="text" name="Search" class="input" required/>

.SearchBar:focus-within {
    border-color: transparent;
    .label, .input:valid + .label {
        transform: scale(0.8) translateY(-5rem);    
    }
}

Similarly, moving the transformation outside the ".SearchBar:focus-within" class did not resolve the issue:

.label, .input:valid + .label {
    transform: scale(0.8) translateY(-5rem);    
}

I also attempted a solution related to autofill scenarios, as recommended here, but encountered the same problem once again.

Furthermore, experimenting with alternate syntax like using "&" instead of nesting classes produced no different outcome:

.SearchBar:focus-within {
        border-color: transparent;
        .input {
            &:focus, &:not(:placeholder-shown) &:-webkit-autofill{
                &+label {
                    transform: scale(0.8) translateY(-5rem);
                }
            }    
        }   
    }

I seem to be overlooking something crucial and unable to pinpoint the issue. At this stage, I can either achieve the label movement upon focus or have it permanently positioned above the text input, which is the final state I desire. Any insights or suggestions would be greatly appreciated.

Answer №1

To ensure there is text inside the input and maintain focus, utilize the :valid CSS selector.

HTML:

<div class="UserForm">
   <input type="text" name="Username" class="input" required/>
   <label class="label" for="Username">Username</label>
</div>

CSS:

.UserForm {
  position: relative;
  width: 300px;
  margin: 3rem auto;
}

.input {
  display: block;
  border: 1px solid #333;
  outline: none;
  padding: 0.8rem;
  font-size: 1.6rem;
  font-weight: bold;
  z-index: 2;
  width: 300px;
}

.label {
  z-index: 1;
  font-size: 1.6rem;
  color: #777;
  position: absolute;
  top: 10px;
  left: 0.8rem;
  vertical-align: middle;
  transform-origin: 0%;
  transition: all ease-in-out 300ms;
  pointer-events: none;
}

.UserForm {
  .input:valid + .label {
    color: #111;
    transform: scale(0.75) translateY(-3rem) translateX(-0.6rem);
  }
}

See a live example Here

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

Is it possible to display different components based on language selection using i18n?

I'm currently developing an application using React and incorporating i18next for internationalization. I have a requirement to dynamically change the banner based on the language selected by the user. Can this be achieved within the i18next framework ...

Issue in Next.js 13: Byte index exceeds limits when running 'npm run dev' command

When attempting to install Next.js 13.4.12, I utilized the command npx <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="385b4a5d594c5d15565d404c1559484878090b160c1609">[email protected]</a>. The installation process ...

How can I change the text of a single button by clicking on it without affecting the other buttons that share the same

Currently, I am implementing a posting system where posts can be added using a button. The posts have two additional buttons - one to show/hide content and the other to delete content. I am utilizing jQuery's slideToggle event to toggle the visibility ...

What is the best way to arrange these divs one on top of another?

I have combed through numerous resources but still haven't found a solution to my problem. I am struggling with figuring out how to stack the "top_section" div on top of the "middle_section" div. Currently, "middle_section" is appearing above "top_sec ...

Stripping CSS prefixes upon file initialization

When developing my application, I have a process in place where I load CSS files on the back-end using Express.JS and then transmit them to the front-end. However, before sending the CSS code to the front-end, I need to: Identify the user's browser; ...

Unable to execute JavaScript function by clicking

I've tried everything, but I can't seem to change the button text when selecting an item in the "Requirements" dropdown. You can view the issue on this site. Located at the bottom of the page is the "Requirements" dropdown. Each item has an oncl ...

Sharing data between components with NextJS 14 and the app router: A guide

I am only 20 days into exploring Next.js, so there are probably some things I am missing. Right now, I have a dashboard page that is server side rendered and consists of 3 components. One of the components contains a button that, upon clicking, should upda ...

Leveraging HTML5 file uploads alongside AJAX and jQuery

While there are questions with similar themes on Stack Overflow, none seem to quite fit the bill for what I am looking for. Here's my goal: Upload an entire form of data, including a single file Utilize Codeigniter's file upload library So fa ...

Handling multiple promises with JavaScript/Express Promise.all()

For my latest project, I am developing a movie discussion forum where users can create profiles and list their favorite films. To display the details of these movies, I have integrated the OMDB API with a backend route built using Express. In my initial t ...

How to add suspense and implement lazy loading for a modal using Material-UI

Currently, I am implementing <Suspense /> and lazy() to enhance the performance of my project. While everything seems to be working smoothly, I have observed some minor changes in DOM handling that are causing me slight confusion. Consider this scen ...

Assertion error: 1 does not match the expected value of 6

I am faced with a challenging test that requires me to write code that will pass successfully. However, no matter what I try, all I get is the following error messages: "Failed asserting that 1 matches expected 6" when I return 6 and "Too few arguments t ...

What is the preferred method for logging out: using window.location.replace('/') or setting window.location.href to window.location.origin?

When it comes to a logout button, which is the better option: window.location.replace('/') or window.location.href=window.location.origin? Can you explain the difference between these two methods? It's my understanding that both of them remo ...

Is there a way to showcase a single HTML canvas across multiple div elements?

I'm currently developing a web application that includes a Google Maps feature in two different tabs using Twitter Bootstrap. I am exploring options to have one canvas element that can be displayed in both tabs with varying dimensions. One idea is to ...

Automatic Submission based on Checkbox Selection

Creating a user-friendly interface for project admins is my goal, but I am encountering difficulties in displaying all tasks. The data is retrieved from the database and put into a table, with each task having a status represented by a binary value - 1 f ...

Having trouble with dynamic routes in NextJS 13? Learn how to get them working properly!

Currently, I am facing an issue with implementing dynamic routes in my NextJS 13 project. The goal is to have a URI structure like blogs/id/, where the id part should be dynamic. Unfortunately, it seems that this setup is not working as expected, and inste ...

What is the best way to connect to my shop through RTK-Query API?

Is there a way to access my redux-toolkit store data from within the rtk-query endpoints? How can I retrieve information from my store in the query or transformResponse methods? import { createApi } from '@reduxjs/toolkit/query/react' import cus ...

Creating HTML elements dynamically based on the value of a prop within a React component

In my React component built using Typescript, it takes in three props: type, className, and children The main purpose of this component is to return an HTML element based on the value passed through type. Below is the code for the component: import React ...

Isotope animation glitches causing malfunction

I've been experimenting with CSS3 transitions on isotope items, but I'm encountering some strange behavior. My goal is to achieve a fading effect on the items, similar to this example: . Thank you in advance! Here's what I have so far: http ...

Tips for circumventing the use of responsive tables in Buefy

I am facing a challenge with displaying data in a Buefy table in a way that it appears as a conventional table with columns arranged horizontally on all devices, rather than the stacked cards layout on mobile. In order to accommodate the content appropriat ...

Enter the ISO code for the country in an HTML form to submit

I'm currently working on a form that requires users to select a country from a list. I came across a website that provides a comprehensive list of countries in HTML format. However, the site displays the full country name but sends the ISO code to the ...