Tạo hiệu ứng khi ẩn hiển các thành phần trong 1 khối div?

Chào các bạn
Mình cần tạo 1 toogle button, ẩn hiện 1 số thành phần trong cột màu xám phía bên trái như hình dưới

id của cột xám là id=“hidden-main-left”
mình dùng đoạn mã này để ẩn tất cả các thành phần ở cột xám đó

function hiddenMainLeft() {
    var hidden = document.getElementById('hidden-main-left');
    if (hidden.style.display === 'none') hidden.style.display = 'block';
	else hidden.style.display = 'none';
}

và đã ẩn hiện được mỗi khi bấm vào button 3 gạch ngang, nhưng nó hiện với ẩn nhanh quá, bụp phát mất, bụp phát hiện :smile: mình muốn cho nó hiện từ từ, và mất từ từ thôi, làm thế nào nhỉ
Xincamon

Bạn gán cho cái div muốn ẩn/hiện 1 cái class, giả sử class hiện là .show, ẩn là .hiden, khi đó chỉ cần css cho nó như này là được:

.show, .hiden {
        /* we specify the transition length for hiding and showing */
        transition: margin-left .4s ease-in;
        -webkit-transition: margin-left .4s ease-in;
    }

    .hiden {
        display: none;
    }

    .show {
        display: block;
    }
2 Likes

div muốn ẩn hiện là chung 1 cái thì gán class show, với hidden ntn bạn

html

<div class="main-left" id="hidden-main-left">
    <div class="main-left-inner-fixed">
        <div class="profile">
            <p>profile</p>
        </div>
        <div class="nav">
            <p>nav</p>
        </div>
    </div>
</div>

css

.main-left {
  flex: 0 0 230px; 
  min-height: 100vh;
  background: #222d32;
}

js

function hiddenMainLeft() {
    var hidden = document.getElementById('hidden-main-left');
    if (hidden.style.display === 'none') hidden.style.display = 'block';
	else hidden.style.display = 'none';
}

Dùng .addClass.removeClass của JQuery bạn nhé. Khi cần hiện thì addClass(“show”) đồng thời removeClass(“hiden”) và ngược lại.

1 Like

Có thể tham khảo từ VueJS, các framework khác cũng có cách làm tương tự.

1 Like

có cách nào đơn giản hơn không @hungaya , mình mới học web căn bản, đạng xây dựng 1 blog nhỏ nhỏ để vừa làm vừa học cho thực tế, vì cấu trúc blog cũng đơn giản nên mình code thủ công :smile: chưa muốn học và dùng fw, để biết tự xây dựng được 1 trang web như thế nào, có cách nào dùng mấy fw kia nhưng thêm theo thành phần riêng lẻ mà k cần thêm cả thư viện vào k nhỉ

Bạn nghiên cứu hai hàm setIntervalsetTimeout để đạt mục đích. Bạn có ý thức né mấy cái framework khi còn căn bản là rất tốt, vì ai sớm “bập vào nó” chẳng khác nào chưa học đứng tấn và các thế cơ bản đã muốn vác vũ khí (framework) đi đánh nhau có khi tự sát thương và chết trước khi trở thành lập trình viên.

3 Likes

Tất nhiên vẫn có cách làm mà ko cần đến thư viện nào, nhưng thư viện sinh ra là để cho việc code dễ dàng, nhanh chóng hơn.
Trong trường hợp của bạn, bạn nên biết là thuộc tính display là thuộc tính trạng thái của element, tức là có hoặc ko, nên bạn ko thể dùng display nếu muốn nó xảy ra chậm được. Muốn xảy ra chậm phải dùng thuộc tính kiểu transform hoặc transition, trong trường hợp này bạn sẽ ko dùng display none nữa mà hãy dùng cách đơn giản nhất là đưa width và height về 0 đi. Xem ví dụ:
https://www.w3schools.com/cssref/tryit.asp?filename=trycss3_transition

2 Likes

Thì có thể tự viết 1 JS Module riêng để thực hiện animation.
JS thuần vẫn phải viết 1 cái khung sườn MVC, đâu phải là lồng ghép Model với View như jQuery đâu.

1 Like

Mình quên mất là có thể dùng javascript, bạn có thể tham khảo cách của @superthin, cách của mình là dùng css.

2 Likes

Về toggle menu, mình có cách sử dụng CSS thuần.
Tạo 1 checkbox rồi ẩn nó đi. Vị trí checkbox và vị trí 3 gạch ngang trùng nhau. Menu xuất hiện hay không tuỳ vào trạng thái của checkbox. Nếu checkbox check mở menu, không check đóng menu.
Cách này chỉ phù hợp khi animation mở menu tương tự animation đóng, cũng chỉ có 2 trạng thái đặt animation (checked, not checked)

Cách tổng quát, dễ custom vẫn cần phải có 1 JS Animation Module riêng, linh hoạt giữa việc gắn CSS animation hay JS animation, lợi về maintain.

2 Likes

mình áp dụng thử cách của bạn, thay đổi độ rộng của div cần cẩn, rồi thêm transition để cho mượt
toàn bộ thành phần trong div main-left html cần ẩn, ví dụ ở đây có 2 cái là profile, nav

<div class="main-left" id="hidden-main-left">
        <div class="profile">
            <p>profile</p>
        </div>
        <div class="nav">
            <p>nav</p>
        </div>
</div>

button để bật ẩn hiện ( 3 gạch)

<button type="button" class="button-toggle" onClick="hiddenMainLeft();">
		  <i class="icon-menu"></i>
</button> 

css

  .main-left {
  flex: 0 0 230px; /* don't grow, don't shrink, stay fixed at 230px */
  min-height: 100vh;
  background: #222d32;
  transition: 0.5s;
}

.hidden {
  flex: 0 0 0px; 
}

js

function hiddenMainLeft() {
   var left = document.getElementById('hidden-main-left');
   if (left.getAttribute('class') == 'main-left') {
   		// if (hidden.style.display === 'none') hidden.style.display = 'block';
   		left.setAttribute('class', 'main-left hidden');
   }
   else {
   		left.setAttribute('class', 'main-left');
   		// hidden.style.display = 'none';
   	}
}

tuy nhiên đây chỉ mới giải quyết được cái nền, nó sẽ ẩn hiện mượt, nhưng thành phần bên trong vẫn chưa ẩn được, mình dùng lai display: none cho từng thành phần thì lại mất hiệu ứng trượt như ở trên bạn đã nói, :smile: giải pháp nào không nhỉ
khi ẩn phần màu xám đi thì element bên trong mình k biết xử lý ntn để vẫn giữ được hiệu ứng

mình thử cách setInterval và setTimeout thì thấy cách hiển thị không đúng ý mình muốn

Kết hợp width: 0 và opacity: 0
Nên thay class hidden thành main-left-hidden để không conflict về sau

1 Like

như thế sẽ mất hiệu ứng từ từ trượt vào của phần màu xám, bụp phát nó vào luôn, bụp phát ra luôn, quay về như ban đâu
bỏ display: none thêm mỗi opacity: 0;
thì ra thế này :smile:

1 Like

Vì do right là background luôn nên không biết làm thế nào. Right là background thì nó không di chuyển, chỉ có left di chuyển.

Trường hợp left, right đồng thời di chuyển thì có 1 parent chứa left và right. Set background-color cho parent, background color: white cho right, left: background-color: transparent.
Animation thì thay translate và scale đồng thời cả left vả right. Left gắn thêm opacity để ẩn hiện text.

<div class="container container-root container-parent">
  <!-- LEFT MENU -->
  <nav class="nav nav-left">
  </nav>

  <!-- RIGHT CONTAINER -->
  <section class="section-main">
    <div class="container"></div>
  </section>
</div>
1 Like

mình dùng flexbox dàn layout, mình tương 2 item (right, left) nằm trên 1 trục thì nó nằm liền nhau chứ

1 Like

Layout là initial state, thay đổi layout khó kiểm soát.
Khi load trang web, browser đọc các layout, render các box. Khi đã render rồi, các box đã có kích thước cố định. Chỉ cần transform trên các box có kích thước cố định.

1 Like

mình sửa lại như bạn nói, nhìn có vẻ ổn, nhưng lại phát sinh ra 1 cái là, mớ text nav, profile chỉ bị mờ đi, chứ k bị ẩn, nên nút button bị nó đè lên, bấm chính giưa k bấm được, bấm vào mép ngoài thì được, click đúp vào chỗ đó sẽ ra google translate cho chữ nav :smile:

1 Like

cho nó position fixed rồi left: -300px là nó biến đi thôi

vọc cái này thử nè

2 Likes

Cách ẩn chữ width: 0 hoặc height = 0;
Khi có thẻ vẫn visible trong DOM, nhưng do diện tích hiển thị = 0 nên không nhận event nào.

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?