Search code examples
htmlcsspaddingmargin

Keep the same margin even if an extra element is added to html


I created a simple example in codesandbox. link: codesandbox I have a textfield with margin bottom. When an error message is set (not empty), margin bottom is set below the error message and the text below gets moved a bit every time error is set/unset.

I want the text below to not move even if the error message is set. Basically set the textfield to have margin bottom with enough space for error message to appear end disappear. The spacing/margin below should look exactly the same, only the text should appear and disappear. How can I achieve this?

HTML:

import "./styles.css";
import { useState, useEffect } from "react";

export default function App() {
  const [name, setName] = useState("");
  const [error, setError] = useState("");

  useEffect(() => {
    if (name !== "") {
      setError("error message");
    } else {
      setError("");
    }
  }, [name]);

  const handleInput = (evt) => {
    setName(evt.target.value);
  };

  return (
    <div className="App">
      <div className="section">
        <div className="container">
          <label>Name :</label>
          <input type="text" name="name" value={name} onChange={handleInput} />
          <span className="error">{error}</span>
        </div>
      </div>
      <div className="blueContent">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
        ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis
        dis parturient montes, nascetur ridiculus mus. Donec quam felis,
        ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
        quis enim
      </div>
    </div>
  );
}

CSS

    .App {
  font-family: sans-serif;
  text-align: center;
}

.container {
  display: flex;
  flex-direction: column;
}

.section {
  margin-bottom: 2rem;
}

.error {
  color: red;
}

.blueContent  {
  background-color: blue;
  color: forestgreen;
  min-height: 200px;
}

Desired result: Result


Solution

  • You can do it by using relative/absolute positioning (you can read more about position here):

    1. Make the parent component positioned relative
    2. Make the error element positioned absolute and use left, right, transform in order to position it in the desired place

    I've edited your CSS:

    .App {
      font-family: sans-serif;
      text-align: center;
    }
    
    .container {
      display: flex;
      flex-direction: column;
      
      /* parent relative */
      position: relative;
    }
    
    .section {
      margin-bottom: 2rem;
    }
    
    .error {
      color: red;
    
      /* child absoluet */
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translate(-50%, 100%);
    }
    
    .blueContent  {
      background-color: blue;
      color: forestgreen;
      min-height: 200px;
    }