0

Yeah I don't really know how to explain this, so here's a diagram of what I want. Basically I want a grid of "items" that's responsive (simple with a grid or flexbox). However I also want it to display a description in a row underneath the currently selected item.

I've got a way to do that but it's not very responsive or extensible (I gotta shift stuff around in the HTML every time I need to insert a new item, which I do a lot).

Here's what I'm currently working with:

<!-- Row 1 -->
<ul class="row">
    <li><a class="tablinks" onclick="openCity(event, 'description1')>Item 1</a></li>
    <li><a class="tablinks" onclick="openCity(event, 'description2')>Item 2</a></li>
    <li><a class="tablinks" onclick="openCity(event, 'description3')>Item 3</a></li>
</ul>

<div id="description1" class="tabcontent">
    <span onclick="this.parentElement.style.display='none';">Description 1</span>
</div>
<div id="description2" class="tabcontent">
    <span onclick="this.parentElement.style.display='none';">Description 2</span>
</div>
<div id="description3" class="tabcontent">
    <span onclick="this.parentElement.style.display='none';">Description 3</span>
</div>

<!-- Row 2 -->
<ul class="row">
    <li><a class="tablinks" onclick="openCity(event, 'description4')>Item 4</a></li>
    <li><a class="tablinks" onclick="openCity(event, 'description5')>Item 5</a></li>
</ul>

<div id="description4" class="tabcontent">
    <span onclick="this.parentElement.style.display='none';">Description 4</span>
</div>
<div id="description5" class="tabcontent">
    <span onclick="this.parentElement.style.display='none';">Description 5</span>
</div>


<!-- onclick script -->
<script>
function openCity(evt, cityName) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName("tabcontent");
    for (i = 0; i < tabcontent.length; i++) {
        tabcontent[i].style.display = "none";
    }
    tablinks = document.getElementsByClassName("tablinks");
    for (i = 0; i < tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(" active", "");
    }
    document.getElementById(cityName).style.display = "block";
    evt.currentTarget.className += " active";
}
function scrollWin() {
    window.scrollTo(0, 0);
}
</script>

What I want is just something similar below, just so I don't have to shuffle stuff around in the html.

<div class="wrapper">
    <div class="item" onclick="showDesc(event, 'description1'>Item 1</div>
    <div class="item" onclick="showDesc(event, 'description2'>Item 2</div>
    <div class="item" onclick="showDesc(event, 'description3'>Item 3</div>
    <div class="item" onclick="showDesc(event, 'description4'>Item 4</div>
    <div class="item" onclick="showDesc(event, 'description5'>Item 5</div>
</div>

<div if="description1" class="description">Description 1</div>
<div if="description2" class="description">Description 2</div>
<div if="description3" class="description">Description 3</div>
<div if="description4" class="description">Description 4</div>
<div if="description5" class="description">Description 5</div>

I don't really care if it uses grid or flexbox or whatever. As long as it works.

Hakase
  • 1
  • 3
  • So there's only one description field, that gets updated based on the selected item? In that case, wouldn't it always come at the bottom? Or do you want it to always appear on the row directly under the selected item? Also note that you **cannot** have duplicate IDs, and on top of this, your desired output has some invalid markup; I assume this was just a copy-paste mistake :) – Obsidian Age Dec 18 '17 at 22:41
  • Yeah just one description field below the selected item. If another item is selected, the old one disappears. My current code places the relevant descriptions after every row, but it's not responsive, so if the page is squished, it will appear two rows down. Sorry about the duplicate IDs I just changed them from my current code for privacy reasons. My employer might be mad if I start throwing peoples names on stack exchange, haha. I fixed the ID's and they are fine on the live version of my site. – Hakase Dec 18 '17 at 22:55

1 Answers1

1

Perhaps not the structure you are looking for but you can take advantage of CSS Grid and the dense auto-flow layout algorithm.

I've used a :hover here but you could spruce it up with a dash of javascript/Jquery.

The concept here is that when shown the "description" automagically fills an entire row (grid-column:1 / -1) which will therefore wrap to form its own row and due to auto-flow:dense the items after it backfill to take up the space left blank.

.container {
  width: 80%;
  margin: auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-flow: row dense;
  grid-gap: 1em;
}

.item,
.desc {
  border: 1px solid grey;
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 30px;
}

.item {
  background: lightblue;
  transition: background 0.25s ease;
}

.item:hover {
  background: rebeccapurple;
}

.item:hover+.desc {
  display: block;
}

.desc {
  background: palegoldenrod;
  display: none;
  grid-column: 1 / -1;
}

@media (min-width: 700px) {
  .container {
    grid-template-columns: repeat(3, 1fr);
  }
}
<div class="container">
  <div class="item">1</div>
  <div class="desc">Description 1</div>
  <div class="item">2</div>
  <div class="desc">Description 2</div>
  <div class="item">3</div>
  <div class="desc">Description 3</div>
  <div class="item">4</div>
  <div class="desc">Description 4</div>
  <div class="item">5</div>
  <div class="desc">Description 5</div>
  <div class="item">6</div>
  <div class="desc">Description 6</div>

</div>

Codepen.io Demo

Paulie_D
  • 107,962
  • 13
  • 142
  • 161
  • That's pretty much exactly what I was hoping for! Thanks! I'll try to figure out a way to make it so it stays active when selected. Could I do something with :focus instead of :hover? I don't have much experience with the interactive parts of CSS. Also I'm still learning the grid layout, why does "grid-column:1 / -1" take up the whole row? Does it mean start at column 1 and span till the end of the row(-1)? – Hakase Dec 20 '17 at 01:25