skip to Main Content

In my app I have a button to expand and collapse a list. The "plus" sign means to expand the list and the "minus" to collapse it. But I seem to be unable to center the plus and minus symbols exactly in the middle of the button. Vertically they both appear in the lower part of it.

That’s what I have so far:

Current

And that’s what I want:

Wanted

Here is my code in CSS:

.accordion-button {
    background-color: transparent;
    border: none;
    cursor: pointer;
    color: white;
    width: 32px;
    height: 32px;
    font-size: 14px;
    font-weight: bold;
    text-align: right;
}

.plus::before {
    content: '02B';
    font-weight: bold;
    font-size: 24px;
}

.minus::before {
    content: '2212';
    font-weight: bold;
    font-size: 24px;
}

The relevant HTML/ТypeScript part of the code:

const [isExpanded, setIsExpanded] = useState<boolean>(false);

const handleAccordionClick = () => {
        setIsExpanded(!isExpanded);
    };

return (
    <button
     className={`accordion-button ${isExpanded ? 'minus' : 'plus'}`}
                    onClick={handleAccordionClick}></button>
);

How can I perfectly center my "plus" and "minus" symbols? Any help is appreciated.

2

Answers


  1. There are several ways to achieve this. In my snippet i’ve used line-height and vertical-align. I also changed the background color of the button for visual purposes.

    EDIT: Thanks to @Parking Master for pointing out that the button text is not centered in Safari. To fix this padding: 0 must be added to the .accordion-button class.

    .accordion-button,
    .accordion-button2 {
        padding: 0;
        border: 0;
        width: 32px;
        height: 32px;
        border-radius: 5px;
        background-color: blue;
        cursor: pointer;
    }
    
    .accordion-button2 {
        width: 64px;
        height: 64px;
    }
    
    .plus::before,
    .minus::before {
        font-weight: bold;
        font-size: 24px;
        line-height: 0;
        vertical-align: sub;
        text-align: center;
        color: white;
    }
    
    .plus::before {
        content: '02B';
    }
    
    .minus::before {
        content: '2212';
    }
    <button class="accordion-button plus"></button>
    <button class="accordion-button minus"></button>
    <br>
    <br>
    <button class="accordion-button2 plus"></button>
    <button class="accordion-button2 minus"></button>
    Login or Signup to reply.
  2. One way to center content is using display: grid; and place-items: center; on the container element containing text.

    const {useState} = React;
    
    const AButton = () => {
      const [isExpanded, setIsExpanded] = useState(false);
      const extraClass = 
        isExpanded ?
        "minus" : "plus";
      return (
        <button
          onClick={
            () =>
            setIsExpanded(!isExpanded)
          }
          className={
            "accordion-button " +
            extraClass
          }
          >
          
        </button>
      );
    };
    
    const App = () => {
      return (
        <div>
          <AButton />
          <AButton />
        </div>
      );
    };
    
    ReactDOM.createRoot(
        document.getElementById("root")
    ).render(<App />);
    .accordion-button {
        background-color: lightblue;
        border: none;
        cursor: pointer;
        color: white;
        width: 32px;
        height: 32px;
        font-size: 14px;
        font-weight: bold;
        text-align: right;
        
        display: inline-grid;
        place-items: center;
        margin: 1rem;
    }
    
    .plus::before {
        content: '02B';
        font-weight: bold;
        font-size: 24px;
    }
    
    .minus::before {
        content: '2212';
        font-weight: bold;
        font-size: 24px;
    }
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>

    Also you could use react to control text content instead of having it be part of a pseudo element in css like so

    const {useState} = React;
    
    const AButton = () => {
      const [isExpanded, setIsExpanded] = useState(false);
      const extraClass = 
        isExpanded ?
        "minus" : "plus";
      return (
        <button
          onClick={
            () =>
            setIsExpanded(!isExpanded)
          }
          className={
            "accordion-button " +
            extraClass
          }
          >
          { isExpanded ? "−" : "+" }
        </button>
      );
    };
    
    const App = () => {
      return (
        <div>
          <AButton />
          <AButton />
        </div>
      );
    };
    
    ReactDOM.createRoot(
        document.getElementById("root")
    ).render(<App />);
    .accordion-button {
        background-color: lightblue;
        border: none;
        cursor: pointer;
        color: white;
        width: 32px;
        height: 32px;
        font-size: 18pt;
        font-weight: bold;
        text-align: right;
        
        display: inline-grid;
        place-items: center;
        margin: 1rem;
    }
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search