A Pen by jakob-e

Thumbnail
This awesome code was written by jakob-e, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright jakob-e ©
  • HTML
  • CSS
  • JavaScript
    <div id="app">
    <vue-card-list v-model="cards"></vue-card-list>
</div>


/*Downloaded from https://www.codeseek.co/jakob-e/a-pen-by-jakob-e-jKrLxv */
    html { box-sizing: border-box; } *,*::before,*::after { box-sizing: inherit; }
body { margin: 0; -webkit-tap-highlight-color: transparent;  }


//  ideas
//  toggle fix position on list 
//  absolut position cards
//  use clip-path on expand/collapse animation
//  .expanded .expanded         active card 
//  .expanded :not(.expanded) 

.list {
    width: 100%; 
    // &.expanded { overflow: hidden; height: 100vh; }
    // &.expanded { position: fixed; }
}
.card {
    $initial-height: 200px;
    position: relative;
    background: whitesmoke;
    height: $initial-height;
    outline:1px solid red; 
    // overflow: hidden;

    .content {
        position: absolute;        
        //         transform: translate3d(0, 0, 0);
        clip-path: inset(0px 0px calc(var(--h, 0) * 1px - #{$initial-height}) 0px);

        transition: 
            clip-path 400ms,
            z-index 800ms
            ;
    }

    &.expanded {
        .content {
            transition: 
                clip-path 400ms,
                z-index 0ms
                ;

            z-index: 9;
            clip-path: inset(0px 0px 0px 0px);
        }
    }




    header {
        // height: 200px;
        background: orange;
        padding: 1em;
        // margin: -1em;

    }
}


/*
🚪 Enter: cubic-bezier(0, .5, .5, 1)
👋 Exit: cubic-bezier(.5, 0, 1, .5)
🌊 Move: cubic-bezier(.5, 0, .5, 1)
*/


/*Downloaded from https://www.codeseek.co/jakob-e/a-pen-by-jakob-e-jKrLxv */
    //  global expanded state
Vue.prototype.$state=new Vue({data:{expanded: null}});



Vue.component('vue-card-list',{
    props:['value'],
    template:`<section class="list" :class="{expanded}">
        <vue-card-item v-for="(item, index) in value" :key="index" v-model="value[index]" />
    </section>`,
    computed:{ expanded(){ return this.$state.expanded; }  }    
});


Vue.component('vue-card-item',{
    props: ['value'],
    template:`<article class="card" :class="{expanded}">
        <div class="content">
            <header>{{ value.id }}</header>
            <section>

    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro beatae est dolores maiores asperiores dolor, repellat et quae saepe sequi perspiciatis deleniti, nemo ducimus doloribus fugiat illum quis? Asperiores, odit.</p>

            </section>
            <footer></footer>
        </div>
    </article>`,
    computed:{ expanded(){ return this.$state.expanded === this; }  },
    watch:{ expanded(){ this.update(); } },
    mounted(){
        addEventListener('resize',this.update);
        this.$el.addEventListener('click',this.toggle); 
        this.update();
    },
    beforeDestroy(){ addRemoveListener('resize',this.update); },
    methods:{
        update(){ 
            this.$el.style.setProperty('--h', this.$el.scrollHeight); 
            console.log(this.height)
        },
        toggle(){ this.$state.expanded = this.expanded ? null: this; },
    }
})


new Vue({el:'#app', data:{
    cards: [
        { id:1},
        { id:2},
        { id:3},
        { id:4},
        { id:5}        
    ]
}})

Comments