Search code examples
htmlcsstwitter-bootstrapbootstrap-4reactstrap

How can I make dropdown menu items width exactly the width of the content?


I am using Reactstrap drop-down menu:

import React from "react";
import {
  Dropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem,
} from "reactstrap";

export default class DropDownTest extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.state = {
      dropdownOpen: false,
    };
  }

  toggle() {
    this.setState((prevState) => ({
      dropdownOpen: !prevState.dropdownOpen,
    }));
  }

  render() {
    return (
      <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
        <DropdownToggle caret>test</DropdownToggle>
        <DropdownMenu>
          <DropdownItem>A</DropdownItem>
          <DropdownItem>A</DropdownItem>
          <DropdownItem>A</DropdownItem>
          <DropdownItem>A</DropdownItem>
        </DropdownMenu>
      </Dropdown>
    );
  }
}

The problem is the DropdownItem width is too large for what I am trying to display the letter A:
enter image description here

I'd like the width of the DropdownItem to be the same of the required width by the inner element. In this case the letter A.

When I inspect the dropdown menu, this is what I see:

   <div
          tabindex="-1"
          role="menu"
          aria-hidden="false"
          class="dropdown-menu show"
          style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(515px, 41px, 0px);"
          x-placement="bottom-start"
        >
          <button
            type="button"
            tabindex="0"
            role="menuitem"
            class="dropdown-item"
          >
            A
          </button>
          <button
            type="button"
            tabindex="0"
            role="menuitem"
            class="dropdown-item"
          >
            A
          </button>
          <button
            type="button"
            tabindex="0"
            role="menuitem"
            class="dropdown-item"
          >
            A
          </button>
          <button
            type="button"
            tabindex="0"
            role="menuitem"
            class="dropdown-item"
          >
            A
          </button>
        </div>

These are the relevant CSS classes:

.dropdown-item {
  display: block;
  width: 100%;
  padding: 0.25rem 1.5rem;
  clear: both;
  font-weight: 400;
  color: #212529;
  text-align: inherit;
  white-space: nowrap;
  background-color: transparent;
  border: 0;
}

And I believe this one is defined in the template that I am using:

.dropdown-menu .dropdown-item {
  color: #66615b;
  font-size: 14px;
  padding: 10px 45px 10px 15px;
  clear: both;
  white-space: nowrap;
  width: 100%;
  display: block;
}

enter image description here

I tried to remove the padding:

  <DropdownItem className="p-0" >A</DropdownItem>
  <DropdownItem className="p-0" >A</DropdownItem>
  <DropdownItem className="p-0">A</DropdownItem>
  <DropdownItem className="p-0">A</DropdownItem>

But, this did not change much as expected.
Any idea how to achieve my goal?


Solution

  • Bootstrap puts a min-width of 10rem on dropdowns (not dropdown items, which should remain 100% width). I determined this by inspecting the elements in my browser's document inspector. Dropdowns actually do take the width of their content over that 10rem minimum. I guess the Bootstrap team just thought skinny dropdowns looked odd.

    You can override this using your custom CSS strategy and a custom class. Including the dropdown-menu class in the selector will ensure precedence.

    .dropdown-menu.min-width-0 {
      min-width: 0;
    }
    

    I assume you'd apply this to the DropdownMenu component. The className property is listed in the ReactStrap docs for that component.

    <DropdownMenu className="min-width-0">