yycvip 发表于 昨天 22:12

原生HTML的<details>折叠面板

借助HTML5的<details>标签,开发者可以不借助JavaScript或其他语言就实现原生的折叠面板。CSS则可以进一步美化外观,并且这一方案具有良好的性能和兼容性。

效果演示


HTML
<h1>Accordion with <code>&lt;details&gt;</code> element</h1>
<p>Making the native <abbr>HTML</abbr> <code>&lt;details&gt;</code> element behave like a typical collapsible accordion with smooth animations.</p>

<p><input type="checkbox" id="accordion-toggle"><label for="accordion-toggle">Keep animations but remove auto-collapse effect </label></p>

<div class="container collapse">
<details>
    <summary>Accordion heading 1</summary>
    <div class="details-wrapper">
      <div class="details-styling">      
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      </div>
    </div>
</details>
<details>
    <summary>Accordion heading 2</summary>
    <div class="details-wrapper">
      <div class="details-styling">      
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      </div>
    </div>
</details>
<details>
    <summary>Accordion heading 3</summary>
    <div class="details-wrapper">   
      <div class="details-styling">      
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quis fuga saepe sunt delectus, quo assumenda dolorum officiis odit optio modi, aspernatur necessitatibus libero, itaque repellendus. Incidunt blanditiis magni velit.</p>
      </div>
    </div>
</details>
</div>

<p>Using the <a href="https://github.com/javan/details-element-polyfill">details-element-polyfill</a> for IE/Edge support</p>// Classes set via JS
$accordionClass: '.collapse-init';
$panelClass: '.panel-active';
$contentsClass: 'summary + *';

/*
Please wrap your collapsible content in a single element or so help me
Must add a transition or it breaks because that's the whole purpose of this
Only one transition-duration works (see explanation on line #141 in JS)
You can add more to an inner wrapper (.details-styling)
*/
//Simplified: .details-wrapper{}
#{$accordionClass $contentsClass} {
transition: all 0.25s ease-in-out;
overflow: hidden; // because we're animating height
}

/*
Closed state. Any CSS transitions work here
The JS has a height calculation to make sliding opened/closed easier, but it's not necessary
Remove the height prop for a simple toggle on/off (after all that work I did for you?)
*/
//Simplified: :not(.panel-active) .details-wrapper {}
#{$accordionClass} :not(#{$panelClass}) #{$contentsClass} {
height: 0;
opacity: 0;
transform: scale(0.9);
transform-origin: bottom center;
}

// Let's get rid of the default arrows so we can style our own, as we must find whatever little joy we can in this garbage web
#{$accordionClass} {
summary { list-style: none; } // Spec
summary::-webkit-details-marker { display: none; } // Chrome
summary::before { display: none; } // Polyfill
   
// Should we do this? No idea
summary { cursor: pointer; }
}

/*
This element exists so .details-wrapper has no extra margin/padding that can screw with the smooth height collapse
You can style .details-wrapper decoratively but avoid anything that modifies the box and add it to .details-styling instead
Otherwise, this element is totally optional. Remove if you hate divitis
*/
.details-styling {
padding: 1em;
}

//======= Non-essential page styling, ignore
$hue: 260;

$background: hsl($hue, 90, 98);
$text: hsl($hue, 20, 25);

$primary: hsl($hue, 85, 50);
$link: hsl($hue, 75, 65);
$border: hsl($hue, 20, 85);

::selection {
$rot: 140;

background: hsl($hue + $rot, 95, 70);
color: adjust-hue($text, $rot);
}

html {
background: $background;
color: $text;
}

body {
font: 1em/1.4 'Quicksand', sans-serif;
margin: 0 auto;
max-width: 960px;
padding: 5vw;
}

h1 {
font-size: 2em;
margin-bottom: 1em;
text-align: center;

+ p {
    margin-left: auto;
    margin-right: auto;
    max-width: 50ch;
}

~ p {
    font-size: 1.2em;
    text-align: center;
}
}

p {
margin-top: 0;
margin-bottom: 1em;

&:last-child { margin-bottom: 0; }
}

code {
$rot: 90;

background: hsla($hue + $rot, 70, 70, 0.1);
color: hsl($hue + $rot - 5, 75, 65);
}

a {
color: $link;
box-shadow: inset 0 -3px lighten($link, 20);
font-weight: 700;
text-decoration: none;
transition: 0.2s;

&:hover,
&:focus {
    box-shadow: inset 0 -1.2em $link;
    color: $background;
}
}

abbr {
font-variant: small-caps;
text-transform: lowercase;
font-size: 1.2em;
}

{
opacity: 0;
position: absolute;
width: 0;
height: 0;

+ label {
    background: lighten($primary, 45);
    border-left: 4px solid $primary;
    cursor: pointer;
    display: block;
    font-size: 1rem;
    font-weight: 700;
    text-align: left;
    transition: 0.1s;
    padding: 0.75em 1em;
   
    &::before {
      border: 2px solid;
      border-radius: 2px;
      color: $primary;
      content: '';
      display: inline-block;
      margin-right: 0.75ch;
      transition: 0.1s;
      width: 1ch;
      height: 1ch;
      vertical-align: baseline;
    }
}

&:focus + label {
    outline: 2px solid $primary;   
}

&:checked + label::before {
    background: currentColor;
    box-shadow: inset 0 0 0 2px #fff;
}
}

.container {
box-shadow: 0.2em 1em 2em -1em $border;
margin: 2.4em 0;
}

//==== Accordion element styling
details {
$b: 6px;

background: #fff;
border: 1px solid $border;
border-bottom: 0;
list-style: none;

&:first-child {
    border-radius: $b $b 0 0;
}

&:last-child {
    border-bottom: 1px solid $border;
    border-radius: 0 0 $b $b;
}
}

summary {
$arrow-size: 0.5em;

display: block;
transition: 0.2s;
font-weight: 700;
padding: 1em;
   
&:focus {
    outline: 2px solid $primary;
}

#{$accordionClass} &::after {
    border-right: 2px solid;
    border-bottom: 2px solid;
    content: '';
    float: right;
    width: $arrow-size;
    height: $arrow-size;
    margin-top: $arrow-size/2;
    transform: rotate(45deg);
    transition: inherit;
}

& {
    background: $primary;
    color: $background;
   
    &::after {
      margin-top: $arrow-size;
      transform: rotate(225deg);
    }
}
}
页: [1]
查看完整版本: 原生HTML的<details>折叠面板