Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Grid how to select row to add hover effect?

I need to select a row to add a hover effect on it. I'm trying to wrap all cells in a row with a div, but all markup is destroyed. Does anyone have any idea how to do it? Is this even possible?

Check here for full code: https://codesandbox.io/s/goofy-easley-w5rrg

const TableWrapperUI = styled.div `
  display: grid;
  box-sizing: border-box;
  width: 100%;
  border: 1px solid #dbeaf4;
  grid-template-columns: repeat(
    ${props => props.columns && props.columns},
    fit-content(400px)
  );
  justify-items: center;
  padding: 5px 0;
  justify-content: space-between;
  > span {
    padding: 5px;
    justify-self: left;
    :hover {
      background: #dbeaf4;
    }
  }`;

const LineUI = styled.div `
  border-bottom: 1px solid #dbeaf4;
  width: 100%;
  grid-column: 1 / -1;
`;
like image 432
Yerlan Yeszhanov Avatar asked Jul 05 '19 12:07

Yerlan Yeszhanov


People also ask

How do you make a hovering effect in CSS?

The :hover selector is used to select elements when you mouse over them. Tip: The :hover selector can be used on all elements, not only on links. Tip: Use the :link selector to style links to unvisited pages, the :visited selector to style links to visited pages, and the :active selector to style the active link.

How do you hover in grid?

If you want to give a hover style to cells, things are simple. Just add some CSS based on the '. wj-cell' class and ':hover' pseudo-selector. If you want to give a hover style to entire rows, apply the hover pseudo-style to the '.

How do I hover a particular element in CSS?

The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device, but does not necessarily activate it. It is generally triggered when the user hovers over an element with the cursor (mouse pointer).

How do I make a row a grid in CSS?

The grid-row CSS shorthand property specifies a grid item's size and location within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start and inline-end edge of its grid area.


1 Answers

display: contents; to the rescue!

Kinda.

Depending on your browser support and/or accessibility requirements, we can achieve the effect you want, using the general structure you have, with the relatively new display: contents property.

Describing display: contents is somewhat difficult, so I'll point to this excellent CSS Tricks article.

To use it, we'll wrap each group of <span> elements in a row into a <div> with display: contents. This allows us to target the div:hover > span elements and apply a background color.

There were a few others small changes required to your styling, like making the <span> elements fill the available width. Here's a working example:

.parent {
  display: grid;
  box-sizing: border-box;
  width: 100%;
  border: 1px solid #dbeaf4;
  grid-template-columns: repeat(4, minmax(15%, max-content));
  padding: 5px 0;
}

.parent span {
  padding: 5px;
  border-bottom: 1px solid #dbeaf4;
}

.row {
  display: contents;
}

.row:hover span {
  background-color: #dbeaf4;
  cursor: pointer;
}
<div class="parent">
  <div class="row">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>Knowledge process outsourcing land the plane yet to be inspired is to become creative, innovative and energized we want this</span>
  </div>
  <div class="row">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
  <div class="row">
    <span>We need to socialize the comms with the wider stakeholder community</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
  <div class="row">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
  <div class="row">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
</div>

With React and Styled Components

Now that we have the CSS working, we can put this back into a styled-components. The main change I've made to your code is to use the <LineUI /> component to wrap each row, along with the new CSS from above.

const titles = [
  "Id",
  "Type",
  "Name",
  "Category",
  "Client",
  "Date",
  "Watched",
  "Amount",
  "State",
  "Delete"
];

const data = [
  {
    id: 23,
    type: "test",
    name: "joaaaahnny cageasdasdasd cageasdasdasd cageasdasdasd cageasdasdasd",
    category: "selasdasler",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 211,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custsdsom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 2222,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 2222,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 2222,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 2222,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  },
  {
    id: 2222,
    type: "test",
    name: "johnny cage",
    category: "seller",
    client: "custom",
    date: "01-01-2019",
    watched: "yes",
    amount: 1231,
    state: "pending",
    delete: "button"
  }
];

const TableWrapperUI = styled.div`
  display: grid;
  box-sizing: border-box;
  width: 100%;
  border: 1px solid #dbeaf4;
  grid-template-columns: repeat(
    ${props => props.columns && props.columns},
    minmax(auto, max-content)
  );
  padding: 5px;

  > * {
    padding: 5px;
  }
`;

const LineUI = styled.div`
  display: contents;
  
  > * {
    padding: 5px;
    border-bottom: 1px solid #dbeaf4;
  }

  :hover > * {
    background-color: #dbeaf4;
    cursor: pointer;
    overflow: visible;
  }
`;

const Table = ({ children, titles, data }) => {
  const [amountColumns, setAmountColumns] = React.useState(0);
  React.useEffect(() => {
    setAmountColumns(titles.length);
  }, []);

  const displayData = data => {
    return data.map((x, idx) => {
      return (
        <React.Fragment key={idx}>
          <LineUI>
            {Object.keys(x).map((value, ids) => (
              <span key={ids}>{x[value]}</span>
            ))}
          </LineUI>
        </React.Fragment>
      );
    });
  };

  const displayTitles = titles => {
    return titles.map((title, idx) => {
      return <span key={idx}>{title}</span>;
    });
  };

  return (
    amountColumns > 0 && (
      <TableWrapperUI columns={amountColumns}>
        {displayTitles(titles)}
        {displayData(data)}
      </TableWrapperUI>
    )
  );
};

function App() {
  return (
    <div className="App">
      <Table columns={10} titles={titles} data={data} />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/styled-components/4.3.2/styled-components.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>


<div id="root"></div>
like image 123
Brett DeWoody Avatar answered Sep 23 '22 08:09

Brett DeWoody