<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Syncopate:wght@100..900&display=swap" rel="stylesheet">

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Syncopate:wght@100..900&display=swap" rel="stylesheet">

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Syncopate:wght@100;700&display=swap" rel="stylesheet">
<style>
  
  <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Syncopate:wght@300;700&display=swap" rel="stylesheet">
<style>
  
@import url('https://fonts.googleapis.com/css2?family=Syncopate:wght@100;700&display=swap');
  
  @import url('https://fonts.googleapis.com/css2?family=Syncopate:wght@100;700&display=swap');
</style>




<div :class="['container', isSelected ? 'container-selected':'', isReady ? 'container-ready':'']" id="app">
  <div class="team-container">
    <div class="header">
      <h2 class="header-title">ARTISTS</h2>
    </div>
    <div class="person-list">
      <div class="person" v-for="(person,index) in persons" @click="selectPerson(index,$event)"><img class="person-img" :src="person.photo">
        <div class="person-details">
          <h2 class="person-title">{{person.name}}</h2>
          <p class="person-desc">{{person.title}}</p>
        </div>
      </div>
    </div>
  </div>
  <div class="team-detail">
    <div class="team-detail-inner" v-if="isOk">
      <div class="team-detail-left" :style=`background-image:url(${selectedPersonData.photo})`>
        <div class="team-detail-photo"><img :src="selectedPersonData.photo" alt="">
        </div>
      </div>
      <div class="team-detail-right">
        <div class="team-detail-bio">
          <div class="team-detail-header">
            <h2 class="person-title">{{selectedPersonData.name}}</h2>
            <p class="person-desc">{{selectedPersonData.title}}</p>
            <div class="social">
              <a :href="selectedPersonData.social.facebook" target="_blank" class="ion-social-facebook"></a>
              <a :href="selectedPersonData.social.twitter" target="_blank" class="ion-social-twitter"></a>
              <a href="selectedPersonData.social.linkedin" target="_blank" class="ion-social-linkedin"></a>
            </div>
          </div>
          <div class="team-detail-bio-content" v-html="selectedPersonData.bio">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
.team-detail-photo {
    position: relative;
    text-align: center;
    z-index: 999;
    width: 100%;
    font-size: 0px;
    DISPLAY: NONE;
}

.person-title {
    color: #fff;
    font-family: Syncopate !important;
    font-size: 2em;
}

$headings-font: "Syncopate", cursive!important;
$body-font: "Snycopate", sans-serif!important;

.team-detail-right .person-title {
    font-family: "Syncopate", cursive !important;
    font-size: 2.2em;
    margin-left: 20px !important;
}

.person-desc {
    color: rgba(255, 255, 255, 0.2);
    margin-top: 10px;
    text-transform: uppercase;
    font-size: 0.8em;
    letter-spacing: 2px;
    margin-left: 20px!important;
}

.social {
    margin-top: 15px;
    margin-left: 20px !important;
}

.team-detail-bio-content p {
    margin-bottom: 15px;
    line-height: 25px;
    font-size: 1.05em;
    margin-left: 20px;
}

.social a {
    color: #ffffff!important;
    font-size: 20px;
    margin-right: 8px;
}

body {
  height: 100%;
  font-family: $body-font;
  background-color: #00020A;
}

.syncopate-regular {
  font-family: "Syncopate", sans-serif;
  font-weight: 800;
  font-style: normal;
}

.syncopate-bold {
  font-family: "Syncopate", sans-serif;
  font-weight: 900;
  font-style: normal;
}


.container {
  width: 100%;
  display: flex;
  align-items: center;
  height: 100vh;
  flex-wrap: wrap;
}
.header {
  width: 100%;
  text-align: center;
  margin-bottom: 45px;
  overflow: hidden;
  transition: 0.45s ease 0.05s;
  max-height: 70px;
  &-title {
    width: 100%;
    font-family: $headings-font;
    font-size: 3.3em;
    color: #ffffff;
    margin-bottom: 15px;
  }
}

.team-container {
  padding: 0 30px;
  box-sizing: border-box;
  max-width: 1400px;
  width: 100%;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  height: auto;
}
.person {
  width: calc(25% - 30px);
  cursor: pointer;
  overflow: hidden;
  transition: 0.45s;
  position: relative;
  &-details {
    padding: 0 20px;
    box-sizing: border-box;
    margin-top: -15px;
    transition: 0.3s;
  }
  &-img {
    width: 100%;
  }
  &-title {
    color: #fff;
    font-size: 2em;
  }
  &-desc {
    color: rgba(#fff, 0.2);
    margin-top: 10px;
    text-transform: uppercase;
    font-size: 0.8em;
    letter-spacing: 2px;
  }
  &-list {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
    justify-content: space-between;
    &:hover {
      .person {
        opacity: 0.6;
      }
    }
  }
  &:hover {
    opacity: 1 !important;
  }
  &:before {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    background: #ffffff;
    content: "";
    height: 0px;
    transition: 0.45s;
  }
  &:after {
    content: "\f2ca";
    font-family: "Ionicons";
    font-size: 36px;
    color: #282828;
    position: absolute;
    width: 100%;
    top: 0;
    height: 100%;
    display: flex;
    opacity: 0;
    visibility: hidden;
    transition: 0.3s;
    text-align: center;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    left: 0;
    flex-direction: column;
  }
}

.container-selected {
  .header {
    max-height: 0px;
  }
  .person {
    opacity: 0 !important;
    pointer-events: none;
  }
  .person-list .person-selected {
    opacity: 1 !important;

    &:before {
      height: 100%;
    }
    .person-details {
      margin-top: -40px;
      opacity: 0;
    }
  }
}
.team-detail {
  position: absolute;
  width: calc(100% - 100px);
  right: 80px;
  top: 0;
  height: 100%;
  color: #fff;
  transition: 0.15s;
  opacity: 0;
  visibility: hidden;
  box-sizing: border-box;
  &-bio {
    &-content {
      p {
        margin-bottom: 15px;
        line-height: 25px;
        font-size: 1.05em;
      }
    }
  }
  &-header {
    margin-bottom: 30px;
  }
  &-inner {
    min-height: 100%;
    display: flex;
    flex-wrap: wrap;
  }
  &-left {
    position: relative;
    width: 650px;
    min-height: 100%;
    background-size: cover;
    background-repeat: no-repeat;
    background-position: top;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    &:before {
      width: 100%;
      height: 100%;
      content: "";
    
      position: absolute;
      right: 0;
      top: 0;
    }
    &:after {
      width: 100%;
      height: 100%;
      content: "";
     

      position: absolute;
      right: 0;
      top: 0;
    }
  }
  &-photo {
    position: relative;
    text-align: center;
    z-index: 999;
    width: 100%;
    font-size: 0px;
    img {
      max-width: 100%;
      box-shadow: 0 10px 22px rgba(0,0,0,.3);
    }
  }
  &-right {
    box-sizing: border-box;
    width: calc(100% - 650px);
    min-height: 100%;
    display: flex;
    align-items: center;
    padding-right: 10%;
    position: relative;
    right: 0;
    flex-wrap: wrap;
    .person-title {
      font-family: $headings-font;
      font-size: 2.2em;
    }
  }
}

.container-ready {
  .team-detail {
    transition: 0.45s ease 0.3s;
    opacity: 1;
    right: 0;
    visibility: visible;
    img {
      width: 75%;
    }
  }
  .team-container {
    height: 0px;
    overflow: hidden;
  }
  .person-selected {
    left: 0px !important;
    top: 0px !important;
    z-index: 99;
    height: 100% !important;
    width: 100px !important;
    pointer-events: auto;
    &:after {
      opacity: 1;
      visibility: visible;
    }
  }
}

.person-back {
  &:before {
    height: 0px !important;
  }
  .person-details {
    margin-top: -15px !important;
    transition-delay: 0.35s;
    opacity: 1 !important;
  }
}

.social {
  margin-top: 15px;
  a {
    color: #fbf9bd;
    font-size: 20px;
    margin-right: 8px;
    &:last-child {
      margin-right: 0;
    }
  }
}
@media (max-width: 1200px) {
  .team-detail-left {
    width: 400px;
    padding: 0 40px;
    box-sizing: border-box;
  }
  .team-detail-right {
    padding-right: 0;
    width: calc(100% - 440px);
  }
  .person .person-title {
    font-size: 1.7em;
  }
  .person-details {
    padding: 0 10px;
  }
}

@media (max-width: 970px) {
  .team-detail-left {
    width: 100%;
    padding: 50px 50px 30px 50px;
    &:after {
      background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0) 0%,
        rgba(33, 33, 33, 1) 83%,
        rgba(40, 40, 40, 1) 100%
      );
    }
  }
  .team-detail-right {
    padding: 0 50px;
    width: 100%;
  }
  .team-detail-header {
    text-align: center;
  }
  .container-ready .person-selected {
    width: 50px !important;
  }
  .team-detail {
    width: calc(100% - 50px);
  }
  .person {
    width: calc(50% - 20px);
  }
}
@media (max-width: 480px) {
  .person {
    width: 100%;
    margin-bottom: 50px;
  }
  .header {
    margin-top: 50px;
  }
}
View Compiled
const persons = [
  {
    name: "Ghost",
    photo: "https://kinder-der-nacht.net/wp-content/uploads/2024/09/Phil.jpg",
    title: "Interpret & DJ",
    bio:
      "<p>Hard-Trance, Peak-Time-Techno & Hard-techno. <br> <br> Als GHOST hat sich der 18-jährige Philip, als talentierter DJ und Veranstalter fest etabliert. Seine musikalischen Wurzeln liegen in den 90er-Jahren, insbesondere im Hardtrance und Rave der Jahre 1993 bis 1996, die seinen Sound maßgeblich prägen und in seine Sets einfließen. <br> <br> Nostalgie und Innovation: GHOST bringt die Sounds der 90er zurück auf die Tanzflächen, indem er selten gespielte Tracks von Labels wie VooDoo Records, Low Spirit, No Respect Records, Bonzai Records und Produzenten wie Jam & Spoon, Commander Tom, Paranoia X und Cocooma auflegt. <br> <br> Mit treibenden Beats von 140 bis 165 BPM kreiert er ein energiegeladenes Erlebnis, das die Vergangenheit in neuem Glanz erstrahlen lässt, während er gleichzeitig moderne Techno-Elemente einfließen lässt. So schafft er eine einzigartige Mischung, die sowohl alteingesessene Raver als auch die jüngere Generation anspricht. Erfolge in der Berliner Clubszene GHOST hat bereits in einigen der bekanntesten Berliner Clubs aufgelegt und sich dort einen Namen gemacht.</p>",
    social: {
      facebook: "#",
      twitter: "https://twitter.com/knyttneve",
      linkedin: "#"
    }
  },
  {
    name: "Sebastian Keks",
    photo: "https://kinder-der-nacht.net/wp-content/uploads/2024/09/Sebastian.jpg",
    title: "Vinyl Dj",
    bio:
      "<p>House, Electro & Techno <br <br> <br> Sebastian Keks: Fast 30 Jahre Leidenschaft für Vinyl und Techno Sebastian Keks ist ein DJ und Produzent aus dem Raum Berlin, der seit 1998 die elektronische Musikszene mit seinen vielseitigen und emotionalen Sets bereichert. <br> <br> Seine musikalische Reise begann bereits im Alter von 13 Jahren, als er seine ersten Underground-Partys besuchte und sich von der pulsierenden Energie der Berliner Clubszene mitreißen ließ. Heute ist er bekannt für seine Fähigkeit, Stimmungen einzufangen und sein Publikum in andere Welten zu entführen. Von Berlin in die Welt: <br> <br> Sebastian hat über die Jahre zahlreiche Projekte ins Leben gerufen, die seinen Einfluss auf die Szene deutlich machen. Eines seiner ersten großen Projekte war Umweltpumpe1 (Up1 Records), das er gemeinsam mit seinem Zwillingsbruder gründete. <br> <br>Mit dieser Crew veranstaltete er zahlreiche Partys, die über die deutschen Landesgrenzen hinaus reichten, wie zum Beispiel im Triebwerk Dresden, Der Weiße Hase Berlin, HdeM Hannover oder auch in Stettin, Polen. Später gründete er die Eventreihen Berlin Techno und Nachteulen, die erfolgreich in Clubs wie dem Bertrams Berlin, Backyard Stettin und Brunnen 70 Berlin stattfanden.</p>",
    social: {
      facebook: "#",
      twitter: "https://twitter.com/knyttneve",
      linkedin: "#"
    }
  },
  {
    name: "Marc Van Linden",
    photo: "https://kinder-der-nacht.net/wp-content/uploads/2024/09/Marc.jpg",
    title: "Label Founder & DJ",
    bio:
      "<p> Trance <br> <br> MVLs DJ & Producer Karriere begann 1996 wo er bei verschiedenen deutschen Independent-Labels, aber in den letzten Jahren hat seine Karriere große Sprünge nach vorne gemacht damit er an vielen Veranstaltungen in der A-League teilnehmen kann! Anfang 2003 lieferte Marc van Linden eine Reihe hochwertiger Remixe ab, die half ihm, seinen Namen in der ganzen Welt zu verbreiten und sich den wohlverdienten Respekt zu verschaffen aus der globalen DJ-Community. <br> <br> 2004 gründete Marc sein eigenes Label Midway Records. Sein Label ist eine Plattform für neue innovative Künstler, sowie Marcs eigene Produktionen. <br> <br>Marc reist derzeit rund um den Globus und präsentiert seine typischen MVL-SOUND. Marc ist bereits in Großbritannien aufgetreten (Turnmills/The Gallery, Ministry of Sound, Goodgreef, Crasher, Wildchild, etc.) Loveparade, Womb in Tokyo, Vandit Night in Berlin, Eden – Ibiza, Länder, die Marc van Linden Gastgeber waren, sind USA, Japan, Australien, China, Kanada, Thailand, Indonesien, Schweden, Estland, Russland, Frankreich, Polen, um nur einige seiner weltweiten Stationen zu nennen. </p>",
    social: {
      facebook: "#",
      twitter: "https://twitter.com/knyttneve",
      linkedin: "#"
    }
  },
  {
    name: "Rob Robsen",
    photo: "https://kinder-der-nacht.net/wp-content/uploads/2024/09/Rob.jpg",
    title: "Producer & DJ",
    bio:
      "<p>Peak-Time-Techno & Hard-techno <br> <br> Rob Robsen: Berliner Techno DJ & Producer mit globaler Reichweite Robert, auch bekannt als Rob Robsen, ist ein Berliner Techno DJ und Producer, der die Techno Szene mit seinem kraftvollen Peak Time Stil begeistert. <br> <br> Als Gründer des Labels Rawtune Records und Mitwirkender bei Kinder der Nacht, steht er für energiegeladenen Peak Time Techno. Seine Sets zeichnen sich durch treibende Beats und eine unverkennbare Härte aus, die sowohl die lokale als auch die internationale Techno-Szene begeistern.<br> <br> Seine Wurzeln liegen in der Berliner Musikkultur, wo er sich auch durch seine Teilnahme am Zug der Liebe und seine legendären Späti Raves einen Namen gemacht hat. Diese Events haben in der Hauptstadt Kultstatus erlangt und seine Verbundenheit zur Berlin unterstrichen. <br> <br>Doch Rob Robsen ist nicht nur auf Berliner Bühnen zu finden. Ein besonderes Highlight seiner Karriere war sein Gig im berühmten Womb Club in Tokio, einem der angesagtesten Clubs der Welt, wo er die japanischen Techno Liebhaber mit seinem unverwechselbaren Sound begeisterte. </p>",
    social: {
      facebook: "#",
      twitter: "https://twitter.com/knyttneve",
      linkedin: "#"
    }
  }
];

const app = new Vue({
  el: "#app",
  data() {
    return {
      persons: persons,
      selectedPersonIndex: null,
      isSelected: false,
      selectedPerson: null,
      inlineStyles: null,
      isReady: false,
      isOk: false,
      selectedPersonData: {
        name: null,
        title: null,
        photo: null,
        social: {
          facebook: null,
          twitter: null,
          linkedin: null
        }
      }
    };
  },
  methods: {
    selectPerson(index, el) {
      if (!this.isOk) {
        this.selectedPersonIndex = index;
        this.isSelected = true;
        el.target.parentElement.className == "person-details"
          ? (this.selectedPerson = el.target.parentElement.parentElement)
          : (this.selectedPerson = el.target.parentElement);

        this.selectedPerson.classList.add("person-selected");
        this.selectedPerson.setAttribute(
          "style",
          `width:${this.selectedPerson.offsetWidth}px;`
        );
        this.selectedPersonData = this.persons[index];
        window.setTimeout(() => {
          this.inlineStyles = `width:${this.selectedPerson
            .offsetWidth}px;height:${this.selectedPerson
            .offsetHeight}px;left:${this.selectedPerson.offsetLeft}px;top:${this
            .selectedPerson.offsetTop}px;position:fixed`;
          this.selectedPerson.setAttribute("style", this.inlineStyles);
        }, 400);
        window.setTimeout(() => {
          this.isReady = true;
          this.isOk = true;
        }, 420);
      } else {
        this.reset();
      }
    },
    reset() {
      this.isReady = false;
      window.setTimeout(() => {
        this.selectedPerson.classList.add("person-back");
      }, 280);
      window.setTimeout(() => {
        this.selectedPerson.setAttribute("style", "");
      }, 340);
      window.setTimeout(() => {
        this.isSelected = false;
        this.selectedPerson.classList.remove("person-back", "person-selected");
        this.isOk = false;
      }, 400);
    }
  }
});

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.2.1/vue-resource.min.js