Меню Аккордеон, CSS, vue

152
31 мая 2021, 04:40

Нужно реализовать меню-аккордеон. При клике на блок с заголовком первого уровня должен плавно "выезжать" сверху вниз блок с контентом. При этом, контент, который будет ниже, нужно чтобы тоже сдвигался вниз (думаю, это логично). При мне знакомый пытался реализовать подобное с помощью max-height: 350px; overflow: hidden; transition: 1s all;, и у него это получилось..Но, похоже, он использовал что-то еще. Ибо для меня этот код не работает. Помогите разобраться, что я упускаю?

new Vue({ 
  el: '#app', 
  data: { 
    isHide: true, 
  }, 
  methods: { 
    open: function() { 
      this.isHide = !this.isHide 
    } 
  } 
}); 
Vue.config.productionTip = false; 
Vue.config.devtools = false;
.pos { 
  display: flex; 
  flex-direction: column; 
  align-items: center; 
} 
 
.all { 
  background: green; 
  width: 400px; 
  height: 40px; 
} 
 
h1, 
h2 { 
  margin: 0; 
  padding: 0; 
  text-align: center; 
  vertical-align: middle; 
} 
 
.hideContent { 
  background: red; 
  width: 300px; 
  height: 100px; 
  max-height: 350px; 
  overflow: hidden; 
  transition: 1s all; 
}
<html> 
 
<body> 
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> 
  <div class="pos" id="app"> 
    <div class="all" @click="open()"> 
      <h1>some title</h1> 
    </div> 
    <div class="hideContent" v-if="isHide==false"> 
      <h2>some content</h2> 
    </div> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
  </div> 
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> 
</body> 
 
</html>

update : Пробовала биндить класс (transition завязываю на height, добавляю класс с изменением height) при изменении значения isHide. Для меня это не работает...Что делаю не так, что упускаю?

new Vue({ 
  el: '#app', 
  data: { 
    isHide: true, 
  }, 
  methods: { 
    open: function() { 
      this.isHide = !this.isHide 
    } 
  } 
});
.pos { 
  display: flex; 
  flex-direction: column; 
  align-items: center; 
} 
 
.all { 
  background: green; 
  width: 400px; 
  height: 40px; 
} 
 
h1, 
h2 { 
  margin: 0; 
  padding: 0; 
  text-align: center; 
  vertical-align: middle; 
} 
 
.hideContent { 
  background: red; 
  width: 300px; 
} 
 
.accordion { 
  overflow: hidden; 
  height: 0px; 
  transition: height 0.3s ease-in-out, box-shadow 0.6s linear; 
} 
 
.accordiooon { 
  transition: height 0.3s ease-in-out, box-shadow 0.6s linear; 
  box-shadow: 0px 0px 0px 1px rgba(155, 155, 155, 0.3); 
  height: 100px; 
}
<html> 
 
<body> 
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> 
  <div class="pos" id="app"> 
    <div class="all" @click="open()"> 
      <h1>some title</h1> 
    </div> 
    <div class="hideContent" :class="{'accordiooon': isHide==false, 'accordion': isHide==true}" v-if="isHide==false"> 
      <h2>some content</h2> 
    </div> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
    <h3>some</h3> 
 
 
  </div> 
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> 
</body> 
 
</html>

update : друзья! хочу еще уточнить, что у меня в качестве контента идет КОМПОНЕНТ с уже заданной ему высотой внутри компонента соответственно. Поэтому, я полагаю, второй вариант для меня и НЕ работает. Какие имеются варианты реализации? Как мне сделать грамотный аккордеон?

Answer 1

Оберните блок с условием в еще один блок и на него уже вешайте классы.

new Vue({ 
  el: '#app', 
  data: { 
    isHide: true, 
  }, 
  methods: { 
    open: function() { 
      this.isHide = !this.isHide 
    } 
  } 
});
.pos { 
  display: flex; 
  flex-direction: column; 
  align-items: center; 
} 
 
.all { 
  background: green; 
  width: 400px; 
  height: 40px; 
} 
 
h1, 
h2 { 
  margin: 0; 
  padding: 0; 
  text-align: center; 
  vertical-align: middle; 
} 
 
.hideContent { 
  background: red; 
  width: 300px; 
} 
 
.accordion { 
  overflow: hidden; 
  height: 0px; 
  transition: all 1s; 
} 
 
.accordiooon { 
  transition: all 1s; 
  height: 100px; 
}
<div class="pos" id="app"> 
  <div class="all" @click="open"> 
    <h1>some title</h1> 
  </div> 
  <div class="hideContent accordion" :class="{'accordiooon': isHide == false}"> 
    <div v-if="isHide==false"> 
      <h2>some content</h2> 
    </div> 
  </div> 
  <h3>some</h3> 
  <h3>some</h3> 
  <h3>some</h3> 
  <h3>some</h3> 
  <h3>some</h3> 
</div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

READ ALSO
Как избавиться от повторений условий внутри if

Как избавиться от повторений условий внутри if

У меня есть много разных условий по типу

96
Visual Studio 2019, вопрос по обозревателю решений

Visual Studio 2019, вопрос по обозревателю решений

Не могу понять, для чего обозреватель решений Visual Studio 2019 имеет разделы Исходные файлы и Файлы заголовков

84
Как мне убрать повторения ненужного кода внутри условия?

Как мне убрать повторения ненужного кода внутри условия?

Все привет :) будьте внимательны пожалуйста

100
Можно ли сделать модификацию функции Эйлера?

Можно ли сделать модификацию функции Эйлера?

Как известно, функция Эйлера ищет количество взаимно простых чисел с N на отрезке [1N]

95