Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 9050

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 28, 20242024-11-28T06:48:09+00:00 2024-11-28T06:48:09+00:00

Creating a Tooltip-like Testimonial with Tailwind and Alpine.js

  • 60k

Live Demo / Download

Testimonials play a crucial role in digital marketing as they serve as social proof of product quality and customer satisfaction. However, a common issue with testimonials is that they often lack visual appeal. In a previous tutorial, we showed how to build a fancy testimonial slider using Tailwind CSS; now, we are doubling down, drawing inspiration from the cool shot by the Significa team. Breaking away from the ordinary, we will build an unconventional testimonial component that looks original while ensuring a good user experience.

Creating the HTML structure

We are going to create a section made of text and images of clients. On hovering over the image, a tooltip will appear with the endorsement message. To create this component, we will use Tailwind CSS and Alpine.js. Alternating text with images may seem simple, but it's trickier than one may think, especially when it comes to align the elements vertically without affecting the line-height of the text. To save time and focus on the functionality, we've prepared the basic HTML structure with the Tailwind CSS utility classes:

<section class="text-center">     <div class="font-nycd text-xl text-indigo-500 mb-4">         <span class="relative inline-flex">             <span>Our promise</span>             <svg class="fill-indigo-500 absolute bottom-0" xmlns="http://www.w3.org/2000/svg" width="132" height="4">                 <path fill-opacity=".4" fill-rule="evenodd" d="M131.014 2.344s-39.52 1.318-64.973 1.593c-25.456.24-65.013-.282-65.013-.282C-.34 3.623-.332 1.732.987 1.656c0 0 39.52-1.32 64.973-1.593 25.455-.24 65.012.282 65.012.282 1.356.184 1.37 1.86.042 1.999" />             </svg>         </span>     </div>     <div class="text-5xl leading-tight font-bold text-slate-900">         <span>We'll help you boost your revenues</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-01.jpg" width="52" height="52" alt="Testimonial 01">             </button>         </div>         <span>manage payrolls</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] -rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-02.jpg" width="52" height="52" alt="Testimonial 02">             </button>         </div>         <span>and save up to 50+ hours in duties every month</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-03.jpg" width="52" height="52" alt="Testimonial 03">             </button>         </div>     </div> </section> 
Enter fullscreen mode Exit fullscreen mode

Now, let's add the tooltips:

<section class="text-center">     <div class="font-nycd text-xl text-indigo-500 mb-4">         <span class="relative inline-flex">             <span>Our promise</span>             <svg class="fill-indigo-500 absolute bottom-0" xmlns="http://www.w3.org/2000/svg" width="132" height="4">                 <path fill-opacity=".4" fill-rule="evenodd" d="M131.014 2.344s-39.52 1.318-64.973 1.593c-25.456.24-65.013-.282-65.013-.282C-.34 3.623-.332 1.732.987 1.656c0 0 39.52-1.32 64.973-1.593 25.455-.24 65.012.282 65.012.282 1.356.184 1.37 1.86.042 1.999" />             </svg>         </span>     </div>     <div class="text-5xl leading-tight font-bold text-slate-900">         <span>We'll help you boost your revenues</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-50">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-01.jpg" width="52" height="52" alt="Testimonial 01">             </button>             <div id="testimonial-01" role="tooltip" class="absolute top-full pt-5">                 <div class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900">                     <div class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3">                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>         <span>manage payrolls</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-40">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] -rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-02.jpg" width="52" height="52" alt="Testimonial 02">             </button>             <div id="testimonial-02" role="tooltip" class="absolute top-full pt-5">                 <div class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900">                     <div                         class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3">                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>         <span>and save up to 50+ hours in duties every month</span>         <div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-30">             <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100">                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-03.jpg" width="52" height="52" alt="Testimonial 03">             </button>             <div id="testimonial-03" role="tooltip" class="absolute top-full pt-5 [&[x-cloak]]:hidden">                 <div class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900">                     <div class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3">                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>     </div> </section> 
Enter fullscreen mode Exit fullscreen mode

Currently, these tooltips are all visible – we will see later how to hide them with Alpine.js. Notice the strategic use of z-50, z-40, and z-30 classes to control the stacking order and prevent tooltips from being covered by underlying images.

Toggling tooltip visibility

Now, we need to integrate some JavaScript logic to handle tooltip visibility, so add an x-data attribute to the element containing the image:

<div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-40" x-data="{ open: false }"> 
Enter fullscreen mode Exit fullscreen mode

Within this directive, we have defined a open property initially set to false, indicating that the tooltip is initially hidden. Next, we want open to become true on hovering over the button, and false when the cursor exits the parent element. To do this, we'll add a @mouseover event to the button and @mouseover.outside to its wrapper:

<div class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-50" x-data="{ open: false }" @mouseover.outside="open = false">     <button class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100" @mouseover="open = true">         <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-01.jpg" width="52" height="52" alt="Testimonial 01">     </button> ... 
Enter fullscreen mode Exit fullscreen mode

Lastly, we'll apply Alpine.js transition utilities for the fade-in/fade-out effect:

<div     id="testimonial-01"     role="tooltip"     class="absolute top-full pt-5 [&[x-cloak]]:hidden"     x-cloak >     <div         class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900"         x-show="open"         x-transition:enter="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-200 delay-100"         x-transition:enter-start="opacity-0 translate-y-2"         x-transition:enter-end="opacity-100 translate-y-0"         x-transition:leave="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-100 delay-100"         x-transition:leave-start="opacity-100"         x-transition:leave-end="opacity-0"                                    >         <div class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3">             <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                 <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />             </svg>             <p>                 This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.             </p>             <p>                 Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>              </p>         </div>     </div> </div> 
Enter fullscreen mode Exit fullscreen mode

Great! Now, the tooltip is hidden by default and fades in – with a subtle vertical translation – when you hover over the image. Also, notice that we have used the x-cloak attribute to prevent the tooltip from briefly appearing before Alpine.js is fully loaded.

Handling keyboard navigation

If you've been following our previous tutorials, you know how important accessibility is to us. That's why, when it comes to implementing this component, we'll make sure that the content can be easily navigated using the keyboard by simply pressing the Tab key. So, let's complete the integration of the button with the addition of a focus event:

<button     class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100"     @mouseover="open = true"     @focus="open = true" >     <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-01.jpg" width="52" height="52" alt="Testimonial 01"> </button> 
Enter fullscreen mode Exit fullscreen mode

Now, the tooltip becomes visible when the button receives focus too. However, we still need to close the tooltip when the container element loses focus:

<div     class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-50"     x-data="{ open: false }"     @mouseover.outside="open = false"     @focusout="await $nextTick();!$el.contains($focus.focused()) && (open = false)" >     <button         class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100"         @mouseover="open = true"         @focus="open = true"     > ... 
Enter fullscreen mode Exit fullscreen mode

At this point, you might be wondering why we didn't just use the expression open = false for the @mouseover event . Well, if there are links or other focusable elements inside the tooltip, we shouldn't close it! That's why we utilized the focus plugin of Alpine.js to determine if the focused element is within the tooltip. If it's not, then we can close the tooltip.

Prevent tooltip overflow

Now, let's ensure the tooltip doesn't overflow the viewport, especially on varying screen sizes. In cases where the tooltip goes outside the screen, particularly on smaller displays, we'll use a few lines of JavaScript to dynamically adjust its positioning. To start, assign an x-ref="tooltip" to the tooltip's container and add an x-init directive to the element defining the background color:

<div     id="testimonial-01"     role="tooltip"     class="absolute top-full pt-5 [&[x-cloak]]:hidden"     x-ref="tooltip"     x-cloak >     <div         class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900"         x-show="open"         x-transition:enter="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-200 delay-100"         x-transition:enter-start="opacity-0 translate-y-2"         x-transition:enter-end="opacity-100 translate-y-0"         x-transition:leave="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-100 delay-100"         x-transition:leave-start="opacity-100"         x-transition:leave-end="opacity-0"                                    >         <div             class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3"             x-init="$watch('open', value => { $nextTick(() => {                 $refs.tooltip.getBoundingClientRect().left < 0 ? $el.style.left = Math.abs($refs.tooltip.getBoundingClientRect().left) + $root.getBoundingClientRect().left - 4 + 'px' : $el.style.left = null;                 $refs.tooltip.getBoundingClientRect().right > document.documentElement.offsetWidth ? $el.style.right = Math.abs($refs.tooltip.getBoundingClientRect().right) - $root.getBoundingClientRect().right - 4 + 'px' : $el.style.right = null;             } )} )"                                              >             <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                 <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />             </svg>             <p>                 This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.             </p>             <p>                 Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>              </p>         </div>     </div> </div> 
Enter fullscreen mode Exit fullscreen mode

In the code above, the $watch method from Alpine.js monitors changes in the open property. When it detects a change, it triggers a function that adjusts the tooltip's position:

  • If the toolptip overflows the screen to the left, it moves the tooltip right.
  • If the toolptip overflows the screen to the right, it moves the tooltip left.

This addition ensures the tooltip remains within the screen boundaries.

Lower sibling opacity on interaction

So far, the component is perfectly functional and accessible, but let's add a subtle enhancement. When a user hovers over an image, we want to decrease the opacity of all other elements. To do this, we'll assign a class bound to the open property:

<div     class="relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-50"     x-data="{ open: false }"     :class="{ 'active': open }"     @mouseover.outside="open = false"     @focusout="await $nextTick();!$el.contains($focus.focused()) && (open = false)" > ... 
Enter fullscreen mode Exit fullscreen mode

In essence, when open is true, the active class is added to the container element. Now, we can use this class to lower the opacity of sibling elements. For those unfamiliar with CSS, the subsequent-sibling combinator (~) can select elements that are siblings occurring after a specific element. So, to lower the opacity of subsequent-sibling elements, we can use the custom class [&.active~*]:opacity-25 on all elements containing text and images. Now, to address the challenge of lowering opacity for preceding elements, we can use the ~ combinator in conjunction with the :has() pseudo-class. This ensures all preceding elements are selected, as explained by Tobias Ahlin Bjerrome. The resulting class is [&:has(~.active)]:opacity-25. Finally, add the transition-opacity and duration-200 classes for a smooth opacity transition effect. With the changes just made, our component is now complete:

<section class="text-center">     <div class="font-nycd text-xl text-indigo-500 mb-4">         <span class="relative inline-flex">             <span>Our promise</span>             <svg class="fill-indigo-500 absolute bottom-0" xmlns="http://www.w3.org/2000/svg" width="132" height="4">                 <path fill-opacity=".4" fill-rule="evenodd" d="M131.014 2.344s-39.52 1.318-64.973 1.593c-25.456.24-65.013-.282-65.013-.282C-.34 3.623-.332 1.732.987 1.656c0 0 39.52-1.32 64.973-1.593 25.455-.24 65.012.282 65.012.282 1.356.184 1.37 1.86.042 1.999" />             </svg>         </span>     </div>     <div class="text-5xl leading-tight font-bold text-slate-900">         <span class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200">We'll help you boost your revenues</span>         <div             class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200 relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-50"             x-data="{ open: false }"             :class="{ 'active': open }"             @mouseover.outside="open = false"             @focusout="await $nextTick();!$el.contains($focus.focused()) && (open = false)"         >             <button                 class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100"                 :class="{ 'rotate-0': open }"                 aria-labelledby="testimonial-01"                 @mouseover="open = true"                 @focus="open = true"             >                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-01.jpg" width="52" height="52" alt="Testimonial 01">             </button>             <div                 id="testimonial-01"                 role="tooltip"                 class="absolute top-full pt-5 [&[x-cloak]]:hidden"                 x-ref="tooltip"                 x-cloak             >                 <div                     class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900"                     x-show="open"                     x-transition:enter="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-200 delay-100"                     x-transition:enter-start="opacity-0 translate-y-2"                     x-transition:enter-end="opacity-100 translate-y-0"                     x-transition:leave="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-100 delay-100"                     x-transition:leave-start="opacity-100"                     x-transition:leave-end="opacity-0"                                                >                     <div                         class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3"                         x-init="$watch('open', value => { $nextTick(() => {                             $refs.tooltip.getBoundingClientRect().left < 0 ? $el.style.left = Math.abs($refs.tooltip.getBoundingClientRect().left) + $root.getBoundingClientRect().left - 4 + 'px' : $el.style.left = null;                             $refs.tooltip.getBoundingClientRect().right > document.documentElement.offsetWidth ? $el.style.right = Math.abs($refs.tooltip.getBoundingClientRect().right) - $root.getBoundingClientRect().right - 4 + 'px' : $el.style.right = null;                         } )} )"                                                          >                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>         <span class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200">manage payrolls</span>         <div             class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200 relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-40"             x-data="{ open: false }"             :class="{ 'active': open }"             @mouseover.outside="open = false"             @focusout="await $nextTick();!$el.contains($focus.focused()) && (open = false)"         >             <button                 class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] -rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100"                 :class="{ 'rotate-0': open }"                 aria-labelledby="testimonial-02"                 @mouseover="open = true"                 @focus="open = true"             >                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-02.jpg" width="52" height="52" alt="Testimonial 02">             </button>             <div                 id="testimonial-02"                 role="tooltip"                 class="absolute top-full pt-5 [&[x-cloak]]:hidden"                 x-ref="tooltip"                 x-cloak             >                 <div                     class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900"                     x-show="open"                     x-transition:enter="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-200 delay-100"                     x-transition:enter-start="opacity-0 translate-y-2"                     x-transition:enter-end="opacity-100 translate-y-0"                     x-transition:leave="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-100 delay-100"                     x-transition:leave-start="opacity-100"                     x-transition:leave-end="opacity-0"                                                >                     <div                         class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3"                         x-init="$watch('open', value => { $nextTick(() => {                             $refs.tooltip.getBoundingClientRect().left < 0 ? $el.style.left = Math.abs($refs.tooltip.getBoundingClientRect().left) + $root.getBoundingClientRect().left - 4 + 'px' : $el.style.left = null;                             $refs.tooltip.getBoundingClientRect().right > document.documentElement.offsetWidth ? $el.style.right = Math.abs($refs.tooltip.getBoundingClientRect().right) - $root.getBoundingClientRect().right - 4 + 'px' : $el.style.right = null;                         } )} )"                                                          >                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>         <span class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200">and save up to 50+ hours in duties every month</span>         <div             class="[&:has(~.active)]:opacity-25 [&.active~*]:opacity-25 transition-opacity duration-200 relative inline-flex justify-center w-[52px] h-[52px] align-middle -translate-y-1 z-30"             x-data="{ open: false }"             :class="{ 'active': open }"             @mouseover.outside="open = false"             @focusout="await $nextTick();!$el.contains($focus.focused()) && (open = false)"         >             <button                 class="h-full w-full focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 rounded-[20px] rotate-[4deg] transition duration-200 ease-[cubic-bezier(.5,.85,.25,1.8)] delay-100"                 :class="{ 'rotate-0': open }"                 aria-labelledby="testimonial-03"                 @mouseover="open = true"                 @focus="open = true"             >                 <img class="absolute top-1/2 -translate-y-1/2 rounded-[inherit]" src="./testimonial-03.jpg" width="52" height="52" alt="Testimonial 03">             </button>             <div                 id="testimonial-03"                 role="tooltip"                 class="absolute top-full pt-5 [&[x-cloak]]:hidden"                 x-ref="tooltip"                 x-cloak             >                 <div                     class="relative w-80 after:absolute after:-top-1.5 after:left-1/2 after:-translate-x-1/2 after:h-3 after:w-3 after:rounded-tl-sm after:rotate-45 after:bg-slate-900"                     x-show="open"                     x-transition:enter="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-200 delay-100"                     x-transition:enter-start="opacity-0 translate-y-2"                     x-transition:enter-end="opacity-100 translate-y-0"                     x-transition:leave="transition ease-[cubic-bezier(.5,.85,.25,1.8)] duration-100 delay-100"                     x-transition:leave-start="opacity-100"                     x-transition:leave-end="opacity-0"                                                >                     <div                         class="relative bg-slate-900 p-5 rounded-3xl shadow-xl text-left text-sm text-slate-200 font-medium space-y-3"                         x-init="$watch('open', value => { $nextTick(() => {                             $refs.tooltip.getBoundingClientRect().left < 0 ? $el.style.left = Math.abs($refs.tooltip.getBoundingClientRect().left) + $root.getBoundingClientRect().left - 4 + 'px' : $el.style.left = null;                             $refs.tooltip.getBoundingClientRect().right > document.documentElement.offsetWidth ? $el.style.right = Math.abs($refs.tooltip.getBoundingClientRect().right) - $root.getBoundingClientRect().right - 4 + 'px' : $el.style.right = null;                         } )} )"                                                          >                         <svg class="fill-indigo-500" xmlns="http://www.w3.org/2000/svg" width="17" height="14" aria-hidden="true">                             <path fill-rule="nonzero" d="M2.014 3.68c.276-1.267.82-2.198 1.629-2.79C4.453.295 5.627 0 7.167 0c.514 0 .908.02 1.185.061L5.035 10.49c-.75 2.494-2.429 3.66-5.035 3.496L2.014 3.68Zm8.648 0c.237-1.227.77-2.147 1.6-2.76C13.09.307 14.274 0 15.814 0c.514 0 .909.02 1.185.061L13.683 10.49c-.79 2.494-2.468 3.66-5.035 3.496L10.662 3.68Z" />                         </svg>                         <p>                             This component is AWESOME. The hover feature is well-thought-out. Even the smaller details, like using colors, really helps everything stay organized. Cruip is amazing and I really enjoy using it.                         </p>                         <p>                             Mary Smith <span class="text-slate-600">-</span> <span class="text-slate-400">Software Engineer</span>                          </p>                     </div>                 </div>             </div>         </div>     </div> </section> 
Enter fullscreen mode Exit fullscreen mode

Conclusions

This tutorial is yet another demonstration of how powerful and versatile the Tailwind CSS + Alpine.js combo is. With just a few lines of code – all within the HTML document! – we have created an interactive, accessible, and responsive component. If you've found this tutorial useful, we recommend checking out our HTML templates built with Tailwind, all designed with Alpine.js. Feel free to experiment further, customize the component to suit your needs, and explore additional features that Tailwind CSS and Alpine.js have to offer. Happy coding!

htmltailwindcsstutorialwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.