Search code examples
cssclickfocusexpandtabindex

CSS: click-to-mutate div, with clickable buttons inside. :focus with tabindex, possibly?


In search of: CSS only, or comprehensible, small jquery. I've already written out exactly what I want in CSS only, using ":focus" and "tabindex="1"".

Objective:
- Click on div = div expands. (note: heavy CSS changing of multiple elements)
- Expanded div has child buttons inside.
- Child buttons clickable.

This worked like a charm with ":focus" and "tabindex="1"", but clicking on an the link inside the div removes the focus, and reverses the div expansion. I thought this workaround worked. But nay.

Here is a JSfiddle of what I've created (This is for an archives page on a webcomics site.) I have left all the styling, so you may understand exactly what I'm intending:

https://jsfiddle.net/gvs291wf/1/

.comicselector {
  width: 200px;
  height: 200px;
  transition: .3s;
  margin: 0 auto 45px;
  display: flex;
}

.comicselector:hover {
  box-shadow: -5px 0px 20px 10px hsla(0, 0%, 0%, .4), 5px 0px 20px 10px hsla(0, 0%, 0%, .4);
}

.comicselector:focus {
  width: 400px;
  height: 500px;
  outline-width: 0;
  box-shadow: -30vw 0 0px 0px hsla(280, 0%, 10%, 0.5), 30vw 0 0px 0 hsla(280, 0%, 10%, 0.5);
  z-index: 101;
  cursor: default;
}

.comimg {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #840;
}

.comimgtitle {
  font-family: 'Days One', sans-serif;
  font-size: 3em;
  font-weight: 800;
  text-shadow: 0px 2px 15px hsla(0, 0%, 0%, 1);
  margin: auto;
  transition: 0.3s;
}

.comicselector:focus .comimgtitle {
  opacity: 0;
  font-size: 0;
}

.comimgauthor {
  font-size: 2em;
  font-weight: 800;
  text-shadow: 0px 2px 15px hsla(0, 0%, 0%, 1);
  font-variant: small-caps;
  margin: auto;
  transition: 0.3s;
}

.comicselector:focus .comimgauthor {
  opacity: 0;
  font-size: 0;
}

.cominfo {
  flex: 0;
  background: hsla(190, 50%, 45%, 1);
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
  transition: .4s;
}

.comicselector:focus .cominfo {
  flex: 1;
}

.infochild {
  font-size: 0;
  transition: 0s;
}

.comicselector:focus .infochild {
  margin: auto;
  z-index: 110;
  transition: .5s;
}

.comictitle {
  padding: 20px 0;
}

.comicselector:focus .comictitle {
  font-size: 3em;
  text-shadow: 0px 4px 20px hsla(0, 0%, 35%, .4);
}

.comicselector:focus .comicauthor {
  font-weight: 700;
  font-size: 2em;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  pointer-events: none;
}

.comicselector:focus .startbeg {
  width: 42%;
  min-height: 70px;
  background: hsla(0, 0%, 35%, 0.4);
  color: #fff;
  font-size: 1em;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-decoration: none;
  margin: 15% auto 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.comicselector:focus .startbeg:hover {
  text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
  box-shadow: -230px 0 0px 0px hsla(280, 0%, 10%, 0.1), 230px 0 0px 0 hsla(280, 0%, 10%, 0.1), 0px 0px 24px 6px hsla(0, 0%, 20%, 0.1);
  background: hsla(0, 60%, 50%, 1);
}

.comicselector:focus .startlatest {
  width: 42%;
  min-height: 50px;
  background: hsla(260, 0%, 35%, 0.4);
  color: #fff;
  font-size: 1em;
  text-decoration: none;
  margin: 1% auto 8%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.comicselector:focus .startlatest:hover {
  text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
  box-shadow: -230px 0 0px 0px hsla(280, 0%, 10%, 0.1), 230px 0 0px 0 hsla(280, 0%, 10%, 0.1), 0px 0px 24px 6px hsla(0, 0%, 20%, 0.1);
  background: hsla(260, 60%, 50%, 1);
}

.seriesinfo {
  font-size: 0;
  opacity: 0;
}

.comicselector:focus .seriesinfo {
  opacity: 1;
  width: 100%;
  box-sizing: border-box;
  min-height: 100px;
  padding: 30px 10%;
  font-size: 1.2em;
  line-height: 1.2em;
  text-align: center;
  background: hsla(260, 0%, 0%, 0.1);
}

.comicselector:focus .eachseriesnav {
  width: 100%;
  box-sizing: border-box;
  padding: 15px 10%;
  font-size: 1.2em;
  background: hsla(260, 0%, 0%, 0.1);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.comicselector:focus .chapnavlinks {
  color: #fff;
  text-decoration: none;
  padding: 10px 16px;
  margin: 2px;
  background: hsla(260, 0%, 0%, 0.1);
  flex-grow: 1;
  transition: 0s;
}

.comicselector:focus .chapnavlinks:hover {
  text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
  box-shadow: 0px 0px 15px 2px hsla(0, 0%, 20%, 0.6);
  background: hsla(260, 50%, 45%, 1);
  transition: .5s;
}
<div class="comicselector" tabindex="1">
  <div class="comimg">
    <div class="comimgtitle">Title</div>
    <div class="comimgauthor">Author</div>
  </div>
  <div class="cominfo">
    <div class="comictitle infochild">title2</div>
    <div class="comicauthor infochild">author2</div>
    <a href="#" class="startbeg infochild">Start</a>
    <a href="#" class="startlatest infochild">Latest Release</a>
    <div class="seriesinfo infochild">comicdescrip
    </div>
    <div class="eachseriesnav infochild">
      <a href="" class="chapnavlinks">Chapter 1,2,etc</a>
    </div>
  </div>
</div>

Thank you!


Solution

  • I think that this should do what you intended. For each .comicselector there is a <label> that controls a hidden radio button. When the radio button is :checked the respective .comicselector has the behavior you want for the :focus. Since all radio buttons belong to the same group via the name attribute, checking one unchecks the current selected one.

    When a radio is checked we hide the corresponding label (display: none), to prevent the .comicselector from closing by clicking it.

    I've also added a background label to enable closing the selected .comicselector from outside.

    watch the snippet in the full page mode

    .bg__label {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
    }
    
    .comicselector {
      position: relative;
      width: 200px;
      height: 200px;
      transition: .3s;
      margin: 0 auto 45px;
      display: flex;
    }
    
    .comicselector:hover {
      box-shadow: -5px 0px 20px 10px hsla(0, 0%, 0%, .4), 5px 0px 20px 10px hsla(0, 0%, 0%, .4);
    }
    
    .comicselector__overlay {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
    }
    
    .check {
      position: absolute;
      z-index: -1;
      visibility: hidden;
    }
    
    .check:checked+.comicselector>.comicselector__overlay {
      display: none;
    }
    
    .check:checked+.comicselector {
      width: 400px;
      height: 500px;
      outline-width: 0;
      box-shadow: -30vw 0 0px 0px hsla(280, 0%, 10%, 0.5), 30vw 0 0px 0 hsla(280, 0%, 10%, 0.5);
      z-index: 101;
      cursor: default;
    }
    
    .comimg {
      flex: 1;
      display: flex;
      flex-direction: column;
      background: #840;
    }
    
    .comimgtitle {
      font-family: 'Days One', sans-serif;
      font-size: 3em;
      font-weight: 800;
      text-shadow: 0px 2px 15px hsla(0, 0%, 0%, 1);
      margin: auto;
      transition: 0.3s;
    }
    
    .check:checked+.comicselector .comimgtitle {
      opacity: 0;
      font-size: 0;
    }
    
    .comimgauthor {
      font-size: 2em;
      font-weight: 800;
      text-shadow: 0px 2px 15px hsla(0, 0%, 0%, 1);
      font-variant: small-caps;
      margin: auto;
      transition: 0.3s;
    }
    
    .check:checked+.comicselector .comimgauthor {
      opacity: 0;
      font-size: 0;
    }
    
    .cominfo {
      flex: 0;
      background: hsla(190, 50%, 45%, 1);
      display: flex;
      flex-direction: column;
      align-items: center;
      overflow: hidden;
      transition: .4s;
    }
    
    .check:checked+.comicselector .cominfo {
      flex: 1;
    }
    
    .infochild {
      font-size: 0;
      transition: 0s;
    }
    
    .check:checked+.comicselector .infochild {
      margin: auto;
      z-index: 110;
      transition: .5s;
    }
    
    .comictitle {
      padding: 20px 0;
    }
    
    .check:checked+.comicselector .comictitle {
      font-size: 3em;
      text-shadow: 0px 4px 20px hsla(0, 0%, 35%, .4);
    }
    
    .check:checked+.comicselector .comicauthor {
      font-weight: 700;
      font-size: 2em;
      letter-spacing: 0.2em;
      text-indent: 0.2em;
      pointer-events: none;
    }
    
    .check:checked+.comicselector .startbeg {
      width: 42%;
      min-height: 70px;
      background: hsla(0, 0%, 35%, 0.4);
      color: #fff;
      font-size: 1em;
      letter-spacing: 0.2em;
      text-indent: 0.2em;
      text-decoration: none;
      margin: 15% auto 0;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .check:checked+.comicselector .startbeg:hover {
      text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
      box-shadow: -230px 0 0px 0px hsla(280, 0%, 10%, 0.1), 230px 0 0px 0 hsla(280, 0%, 10%, 0.1), 0px 0px 24px 6px hsla(0, 0%, 20%, 0.1);
      background: hsla(0, 60%, 50%, 1);
    }
    
    .check:checked+.comicselector .startlatest {
      width: 42%;
      min-height: 50px;
      background: hsla(260, 0%, 35%, 0.4);
      color: #fff;
      font-size: 1em;
      text-decoration: none;
      margin: 1% auto 8%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .check:checked+.comicselector .startlatest:hover {
      text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
      box-shadow: -230px 0 0px 0px hsla(280, 0%, 10%, 0.1), 230px 0 0px 0 hsla(280, 0%, 10%, 0.1), 0px 0px 24px 6px hsla(0, 0%, 20%, 0.1);
      background: hsla(260, 60%, 50%, 1);
    }
    
    .seriesinfo {
      font-size: 0;
      opacity: 0;
    }
    
    .check:checked+.comicselector .seriesinfo {
      opacity: 1;
      width: 100%;
      box-sizing: border-box;
      min-height: 100px;
      padding: 30px 10%;
      font-size: 1.2em;
      line-height: 1.2em;
      text-align: center;
      background: hsla(260, 0%, 0%, 0.1);
    }
    
    .check:checked+.comicselector .eachseriesnav {
      width: 100%;
      box-sizing: border-box;
      padding: 15px 10%;
      font-size: 1.2em;
      background: hsla(260, 0%, 0%, 0.1);
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
    }
    
    .check:checked+.comicselector .chapnavlinks {
      color: #fff;
      text-decoration: none;
      padding: 10px 16px;
      margin: 2px;
      background: hsla(260, 0%, 0%, 0.1);
      flex-grow: 1;
      transition: 0s;
    }
    
    .check:checked+.comicselector .chapnavlinks:hover {
      text-shadow: 0px 2px 12px hsla(0, 0%, 90%, 0.6);
      box-shadow: 0px 0px 15px 2px hsla(0, 0%, 20%, 0.6);
      background: hsla(260, 50%, 45%, 1);
      transition: .5s;
    }
    <input id="check0" type="radio" name="control" class="check" />
    <label for="check0" class="bg__label"></label>
    
    <input id="check1" type="radio" name="control" class="check" />
    <div class="comicselector" tabindex="1">
      <label for="check1" class="comicselector__overlay"></label>
      <div class="comimg">
        <div class="comimgtitle">Title</div>
        <div class="comimgauthor">Author</div>
      </div>
      <div class="cominfo">
        <div class="comictitle infochild">title2</div>
        <div class="comicauthor infochild">author2</div>
        <a href="#" class="startbeg infochild">Start</a>
        <a href="#" class="startlatest infochild">Latest Release</a>
        <div class="seriesinfo infochild">comicdescrip
        </div>
        <div class="eachseriesnav infochild">
          <a href="" class="chapnavlinks">Chapter 1,2,etc</a>
        </div>
      </div>
    </div>
    
    <input id="check2" type="radio" name="control" class="check" />
    <div class="comicselector" tabindex="1">
      <label for="check2" class="comicselector__overlay"></label>
      <div class="comimg">
        <div class="comimgtitle">Title</div>
        <div class="comimgauthor">Author</div>
      </div>
      <div class="cominfo">
        <div class="comictitle infochild">title2</div>
        <div class="comicauthor infochild">author2</div>
        <a href="#" class="startbeg infochild">Start</a>
        <a href="#" class="startlatest infochild">Latest Release</a>
        <div class="seriesinfo infochild">comicdescrip
        </div>
        <div class="eachseriesnav infochild">
          <a href="" class="chapnavlinks">Chapter 1,2,etc</a>
        </div>
      </div>
    </div>