如何在纯HTML/JS中应用Tailwind UI动画

8

我想使用tailwindui.com提供的样例组件。他们在注释中定义了动画部分,但我不知道如何将其应用到我的代码中。我正在使用普通的HTML/JS,并希望不使用任何框架或库。

我在这里尝试显示/隐藏一个模态对话框。背景叠加层的动画效果如下:

 <!--
      Background overlay, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0"
        To: "opacity-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100"
        To: "opacity-0"
    --> 

我不知道如何将这些信息编码到背景遮罩层中。

<div id="myModal" class="hidden fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <!--
      Background overlay, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0"
        To: "opacity-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100"
        To: "opacity-0"
    -->
    <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>

以下是我到目前为止尝试过的内容:

<style>
  .modalEntry {animation:modal-in 1s;}  
  .modalExit {animation:modal-in 1s;}

@keyframes modal-in {
    from {opacity-0;}
    to {opacity-100;}
}
@keyframes modal-out {
    from {opacity-100;}
    to {opacity-0;}
}
</style>

<button class="border border-red-500" onclick="toggleModal()">Toggle modal</button>

<!-- This example requires Tailwind CSS v2.0+ -->
<div id="myModal" class="hidden fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <!--
      Background overlay, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0"
        To: "opacity-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100"
        To: "opacity-0"
    -->
    <div class="fixed modalEntry inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>

    <!-- This element is to trick the browser into centering the modal contents. -->
    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>

    <!--
      Modal panel, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
        To: "opacity-100 translate-y-0 sm:scale-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100 translate-y-0 sm:scale-100"
        To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
    -->
    <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
      <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
        <div class="sm:flex sm:items-start">
          <div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
            <!-- Heroicon name: outline/exclamation -->
            <svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
            </svg>
          </div>
          <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
            <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">Deactivate account</h3>
            <div class="mt-2">
              <p class="text-sm text-gray-500">Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.</p>
            </div>
          </div>
        </div>
      </div>
      <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
        <button onclick="toggleModal()" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">Deactivate</button>
        <button onclick="toggleModal()" type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">Cancel</button>
      </div>
    </div>
  </div>
</div>

<script>
  function toggleModal () {
        document.getElementById("myModal").classList.toggle("hidden");
  }
</script>

为了方便测试,我把它放在CodePen中。

https://codepen.io/rishavs/pen/BadMQaN?editors=1000
2个回答

1
我正在一个传统的PHP项目中使用jQuery,或许你可以从中得到灵感。
首先,在slide-over-title中添加一个id,并建议使用动画效果。
<div class="fixed inset-0 overflow-hidden z-[2000] bg-gray-200 transform transition ease-in-out duration-500 sm:duration-700 translate-x-full" aria-labelledby="slide-over-title" id="slide-over-title" role="dialog" aria-modal="true">

然后创建一个简单的“切换”函数,可以在任何地方使用。
function toggleSlider() {
    if($("#slide-over-title").hasClass("translate-x-full")) {
    $("#slide-over-title").removeClass("translate-x-full");
    $("#slide-over-title").addClass("translate-x-0");
    } else  {
    $("#slide-over-title").addClass("translate-x-full");
    $("#slide-over-title").removeClass("translate-x-0");  
    }
}

在这个片段中,我使用了Tailwind CDN,但是在生产环境中,您应该使用Tailwind预处理器或CLI来生成优化的CSS文件。

function toggleSlider() {
        if($("#slide-over-title").hasClass("translate-x-full")) {
        $("#slide-over-title").removeClass("translate-x-full");
        $("#slide-over-title").addClass("translate-x-0");
        } else  {
        $("#slide-over-title").addClass("translate-x-full");
        $("#slide-over-title").removeClass("translate-x-0");  
        }
    }
<button onclick="toggleSlider()">Toggle Slider</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<div class="fixed inset-0 overflow-hidden z-[2000] bg-gray-200 transform transition ease-in-out duration-500 sm:duration-700 translate-x-full" aria-labelledby="slide-over-title" id="slide-over-title" role="dialog" aria-modal="true">
  <div class="absolute inset-0 overflow-hidden">
    
    <div class="absolute inset-0" aria-hidden="true"></div>

    <div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 sm:pl-16">
      <!--
        Slide-over panel, show/hide based on slide-over state.

        Entering: "transform transition ease-in-out duration-500 sm:duration-700"
          From: "translate-x-full"
          To: "translate-x-0"
        Leaving: "transform transition ease-in-out duration-500 sm:duration-700"
          From: "translate-x-0"
          To: "translate-x-full"
      -->
      <div class="pointer-events-auto w-screen max-w-2xl">
        <div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
          <div class="px-4 sm:px-6">
            <div class="flex items-start justify-between">
              <h2 class="text-lg font-medium text-gray-900" id="slide-over-title">Panel title</h2>
              <div class="ml-3 flex h-7 items-center">
                <button type="button" class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" onclick="toggleSlider()">
                  <span class="sr-only">Close panel</span>
                  <!-- Heroicon name: outline/x -->
                  <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>
            </div>
          </div>
          <div class="relative mt-6 flex-1 px-4 sm:px-6">
            <!-- Replace with your content -->
            <div class="absolute inset-0 px-4 sm:px-6">
              <div class="h-full border-2 border-dashed border-gray-200" aria-hidden="true"></div>
            </div>
            <!-- /End replace -->
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


0

在tailwindui上应用过渡效果而不使用Vue/React的最简单方法是使用Alpine.js,如文档中所述:

  <div
    x-show="isOpen"
    x-transition:enter="transition ease-out duration-100 transform"
    x-transition:enter-start="opacity-0 scale-95"
    x-transition:enter-end="opacity-100 scale-100"
    x-transition:leave="transition ease-in duration-75 transform"
    x-transition:leave-start="opacity-100 scale-100"
    x-transition:leave-end="opacity-0 scale-95"
    class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg"
  >

如果您想自己编写代码,那么您需要确保首先更改显示状态(块/隐藏),然后在应用实际的过渡类之前等待一帧。这是必需的,因为从display:none 更改为 display:block 不会触发css过渡动画(请参见 CSS显示属性上的过渡)。

另外,您需要确保在过渡完成后隐藏元素(例如,对于 duration-200 类,您需要等待 200 毫秒)。否则,它将立即隐藏而没有转换动画。

您可以使用 "visibility" 替代 "display",但这对于模块来说不是一个好选择,因为背景覆盖整个页面并使其他按钮无法点击。

要等待下一次重新绘制之前的一帧,您可以使用 window.requestAnimationFrame() 方法。另一种实现方式是使用setTimeout方法,如https://dev59.com/wVkS5IYBdhLWcg3wCShx#40447192所示。

我实际上找到了一个Github仓库,它仅实现了来自Alpine的这个x-transition,旨在用于Tailwind-UI转换https://github.com/CaptainCodeman/x-transition,经过gzip压缩只有大约1kb,但是Alpine.js经过gzip压缩大约为7kb,并具有大量其他功能,因此我认为直接使用Alpine.js是有意义的。

另外,当您自己实现它或使用Alpine.js时,仍需要确保符合wai aria实践


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接