Как мне убедиться, что height: 0; также включает отступы?

#html #css

#HTML #css

Вопрос:

У меня есть этот аккуратный CSS-аккордеон, который работает все хорошо и хорошо, пока я не попытаюсь добавить отступы или поля к .accordBody .

Вся «магия» аккордеона состоит из простого трюка, увеличения высоты .accordBody от 0 до 125px в :focus соответствии .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> 

Теперь визуально это выглядит не очень эстетично, поскольку отсутствует заполнение .accordBody . Однако, если я сейчас попытаюсь добавить указанное заполнение, дизайн нарушится, поскольку заполнение приведет .accordBody к тому, что, хотя для него height установлено значение 0 , он останется открытым.

 .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> 

Как мне убедиться, что height: 0; это также включает отступы?

Ответ №1:

Добавьте дополнительный контейнер и учитывайте поля вместо отступов

 .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> 

Без дополнительной оболочки вы можете рассмотреть некоторые хитрости с псевдо-элементом:

 .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> 

Комментарии:

1. Спасибо, это решает проблему, однако я хотел бы, чтобы пробелы применялись к исходному .accordBody div, я приму ваш ответ, хотя, если это действительно невозможно.

2. другого пути, кроме этого решения без JS, нет. Даже box-sizing: border-box; не поможет, поскольку он не изменяет высоту отступа или границы. Everythign else будет применять отрицательную высоту, что будет означать, что она становится недействительной.

3. @Simplicius добавил еще одну идею

4. Вы потратили много времени и думали найти такой хакерский подход к моему вопросу, спасибо! Это определенно стоит моего согласия!

Ответ №2:

Для того, чтобы переход заработал, я ввел дополнительный "paddingDiv" и придал ему стиль заполнения

 .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> 

Комментарии:

1. Это сработало бы, однако мне потребовалась бы возможность добавить переход к .accordBody , поскольку display он двоичный и не может быть масштабирован.