Simplicius
Simplicius

Reputation: 2095

How do I ensure that height: 0; includes padding as well?

I have got this neat CSS accordion, which works all nice and fine, until I try to add either padding or margin to the .accordBody.

The entire "magic" of the accordion consists out of the simple trick of, increasing the height of .accordBody from 0 to 125px on the :focus of the according .accordHeader.

.accordion {
  border: solid 1px #cccccc;
  border-radius: 0.25rem;
  box-shadow: 0 2px 4px -1px #b3b3b3;
}

.accordion .accord .accordHeader,
.accordion .accord .accordBody {
  background-color: #fff;
  padding: 1rem;
}

.accordion .accord .accordHeader {
  border-bottom: solid 1px #cccccc;
  color: #000;
  cursor: pointer;
}

.accordion .accord .accordBody {
  padding: 0;
  box-shadow: inset 0px 2px 4px -1px #e6e6e6;
  height: 0;
  transition: height 250ms ease;
  overflow: hidden;
}

.accordion .accord:focus>*~.accordBody {
  height: 125px;
  overflow: auto;
}

.accordion .accord:focus+.accord .accordHeader {
  border-top: solid 1px #cccccc;
}
<div class="accordion">
  <div class="accord" tabindex="0">
    <div class="accordHeader">
      Header
    </div>
    <div class="accordBody">
      Body
    </div>
  </div>
  <div class="accord" tabindex="0">
    <div class="accordHeader">
      Header
    </div>
    <div class="accordBody">
      Body
    </div>
  </div>
  <div class="accord" tabindex="0">
    <div class="accordHeader">
      Header
    </div>
    <div class="accordBody">
      Body
    </div>
  </div>

Now visually this does not look really aesthetically pleasing, since the missing padding of the .accordBody. However if I now try to add said padding, the design breaks, since the padding will cause the .accordBody, though its height is set to 0, to stay open.

.accordion {
  border: solid 1px #cccccc;
  border-radius: 0.25rem;
  box-shadow: 0 2px 4px -1px #b3b3b3;
}
.accordion .accord .accordHeader,
.accordion .accord .accordBody {
  background-color: #fff;
  padding: 1rem;
}
.accordion .accord .accordHeader {
  border-bottom: solid 1px #cccccc;
  color: #000;
  cursor: pointer;
}
.accordion .accord .accordBody {
  box-shadow: inset 0px 2px 4px -1px #e6e6e6;
  height: 0;
  transition: height 250ms ease;
  overflow: hidden;
}
.accordion .accord:focus > * ~ .accordBody {
  height: 125px;
  overflow: auto;
}
.accordion .accord:focus + .accord .accordHeader {
  border-top: solid 1px #cccccc;
}
<div class="accordion">
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
      <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
</div>

How do I ensure that height: 0; includes padding as well?

Upvotes: 2

Views: 571

Answers (2)

bludash
bludash

Reputation: 11

In order for the transition to work I introduced a additional "paddingDiv"and gave it the padding style

.accordion {
  border: solid 1px #cccccc;
  border-radius: 0.25rem;
  box-shadow: 0 2px 4px -1px #b3b3b3;
}

.accordHeader {
  background-color: #fff;
  padding: 1rem;
}

.accordHeader {
  border-bottom: solid 1px #cccccc;
  color: #000;
  cursor: pointer;
}

.accordBody {
  padding: 0;
  box-shadow: inset 0px 2px 4px -1px #e6e6e6;
  height: 0;
  transition: height 250ms ease;
  overflow: hidden;
}

.accordion .accord:focus>*~.accordBody {
  height: 125px;
  overflow: auto;
}

.accord:focus+.accord .accordHeader {
  border-top: solid 1px #cccccc;
}

.paddingDiv {
  overflow: hidden;
  padding: 1rem;
}
<!DOCTYPE html>
<html>
<head>
  <title>Another simple example</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>

  <div class="accordion">
    <div class="accord" tabindex="0">
       <div class="accordHeader">
          Header
       </div>
       <div class="accordBody" visibility="hidden" height="2px">
          <div class="paddingDiv">Body</div>
       </div>
    </div>
    <div class="accord" tabindex="0">
       <div class="accordHeader">
          Header
       </div>
       <div class="accordBody">
          <div class="paddingDiv">Body</div>
       </div>
    </div>
       <div class="accord" tabindex="0">
       <div class="accordHeader">
          Header
       </div>
       <div class="accordBody">
          <div class="paddingDiv">Body</div>
       </div>
    </div>
 </div>

</body>
</html>

Upvotes: 0

Temani Afif
Temani Afif

Reputation: 273448

Add an extra container and consider margin instead of padding

.accordion {
  border: solid 1px #cccccc;
  border-radius: 0.25rem;
  box-shadow: 0 2px 4px -1px #b3b3b3;
}
.accordion .accord .accordHeader {
  background-color: #fff;
  padding: 1rem;
}
.accordion .accord .accordBody {
  background-color: #fff;
}
.accordion .accord .accordBody > div {
  margin:1rem;
}
.accordion .accord .accordHeader {
  border-bottom: solid 1px #cccccc;
  color: #000;
  cursor: pointer;
}
.accordion .accord .accordBody {
  box-shadow: inset 0px 2px 4px -1px #e6e6e6;
  height: 0;
  transition: height 250ms ease;
  overflow: hidden;
}
.accordion .accord:focus > * ~ .accordBody {
  height: 125px;
  overflow: auto;
}
.accordion .accord:focus + .accord .accordHeader {
  border-top: solid 1px #cccccc;
}
<div class="accordion">
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         <div>Body</div>
      </div>
   </div>
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         <div>Body</div>
      </div>
   </div>
      <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         <div>Body</div>
      </div>
   </div>
</div>

Without extra wrapper you can consider some trick with pseudo element:

.accordion {
  border: solid 1px #cccccc;
  border-radius: 0.25rem;
  box-shadow: 0 2px 4px -1px #b3b3b3;
}
.accordion .accord .accordHeader {
  background-color: #fff;
  padding: 1rem;
}
.accordion .accord .accordBody {
  background-color: #fff;
  padding:0 1rem;
}
.accordion .accord .accordBody:before,
.accordion .accord .accordBody:after{
  content:"";
  display:block;
  height:min(100%,1rem); /* don't make it more than 1rem and it will be 0 on collapse due to 100%x0 */
}
.accordion .accord .accordHeader {
  border-bottom: solid 1px #cccccc;
  color: #000;
  cursor: pointer;
}
.accordion .accord .accordBody {
  box-shadow: inset 0px 2px 4px -1px #e6e6e6;
  height: 0;
  transition: height 250ms ease;
  overflow: hidden;
}
.accordion .accord:focus > * ~ .accordBody {
  height: 125px;
  overflow: auto;
}
.accordion .accord:focus + .accord .accordHeader {
  border-top: solid 1px #cccccc;
}
<div class="accordion">
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
   <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
      <div class="accord" tabindex="0">
      <div class="accordHeader">
         Header
      </div>
      <div class="accordBody">
         Body
      </div>
   </div>
</div>

Upvotes: 3

Related Questions