webksde

Swiper.js shows 1px of the upcoming / next slide

There is a GitHub issue for this problem, but there is no working solution and the issue is locked.
The issue does mention setting Swipers‘ roundLengths to true, but this didn’t work for me.

My workaround (for a single slide slideshow):


 .swiper-slide-next {
   translate: 1px 0;
 }

It reliably fixes the problem without affecting the slideshow on devices that don’t have this issue.

Github issue: https://github.com/nolimits4web/swiper/issues/2722

    Solving the „Empty Check“ Race Condition with Drupal’s BigPipe

    As a Drupal themer, you’ve likely encountered situations where you need to remove a block or a wrapper element only if it’s empty. Since Twig templates can’t always perform this check without breaking cacheability (especially for nested elements), a common pattern is to add a specific class, like js-empty-check, and handle the removal with JavaScript.

    The logic seems simple: on page load, find all elements with this class, and if they have no children, remove them.

    The Problem: A Race Against BigPipe

    This approach works perfectly until you factor in Drupal’s BigPipe module. BigPipe improves front-end performance by streaming page content and replacing placeholders with dynamic content after the initial page load.

    This creates a classic race condition. Your js-empty-check script often runs before BigPipe has finished its work. It inspects an element, finds a <data-big-pipe-placeholder> tag inside, and incorrectly concludes that the element is not empty. The wrapper stays, even though the final rendered content might be empty, leaving you with unwanted layout gaps.

    The Solution: Leveraging Drupal Behaviors

    The key to solving this isn’t to try and out-race BigPipe or use complicated event listeners. The solution lies in embracing the Drupal JavaScript API, specifically Drupal.attachBehaviors.

    When BigPipe (or any AJAX request) inserts new content into the DOM, it calls Drupal.attachBehaviors on that new content. We can use this hook to intelligently re-run our check.

    Our implementation works in two stages within the attach function:

    1. Initial Check: It scans for .js-empty-check elements within the current context. If an element contains a BigPipe placeholder, it’s ignored for now. If it’s genuinely empty, it’s removed. If it has content, the class is removed to prevent re-processing.
    2. Post-BigPipe Check: When attachBehaviors is called on new content from BigPipe, we know that a placeholder has just been replaced. Our script then traverses up from that new content (context) to find any parent elements with the .js-empty-check class and re-runs the check on them.

    This ensures that containers are re-evaluated at the exact moment they’ve been populated with their final content.

    The Code

    Here is the implementation within Drupal.behaviors:

    (function ($, Drupal) {
      Drupal.behaviors.myThemeEmptyCheck = {
        attach: function (context, settings) {
          /**
           * Checks a given jQuery element to see if it's effectively empty and removes it if it is.
           * @param {jQuery} $element The element to check.
           */
          function emptyCheck($element) {
            // If the element still contains a BigPipe placeholder, we can't determine its state yet.
            // We'll wait for the placeholder to be replaced, which triggers attachBehaviors again.
            if ($element.find('[data-big-pipe-placeholder-id]').length > 0) {
              return;
            }
    
            // An element is empty if it has no child elements and its trimmed HTML content is empty.
            if ($element.children().length === 0 && $element.html().trim() === '') {
              // Remove the element from the DOM.
              $element.remove();
            } else {
              // It's not empty, so we remove the class to prevent future checks.
              $element.removeClass('js-empty-check');
            }
          }
    
          // 1. Check elements that are themselves the context or are inside the current context.
          $('.js-empty-check', context).each(function () {
            emptyCheck($(this));
          });
    
          // 2. After an AJAX or BigPipe load, the context is the new content.
          //    The .js-empty-check element might be a PARENT of this new content.
          //    We need to find and re-check those parents.
          if (context !== document) {
            $(context)
              .parents('.js-empty-check')
              .each(function () {
                emptyCheck($(this));
              });
          }
        },
      };
    })(jQuery, Drupal);

    By hooking into the standard behavior system, we create a clean, robust, and efficient solution that works with Drupal’s rendering pipeline instead of fighting against it.

      Create a 100vh section without Javascript or position:absolute / fixed (& height:100%) using dvh

      I came across the dvh = „dynamic view height“ unit a couple of years ago, where the browser support was very bad.

      Now we have about 95%, which should be enough for most projects – if not @supports should do the trick, so DVH could be used as an progressive enhancement.

      This is particularly useful when dealing with mobile browsers that hide the address bar when scrolling.

      See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units

      Credits @ Artur A on Stackoverflow.

      Override Form Twig Templates in Drupal 8+ (example: Commerce Cart Form)

      Sometimes you want to add a layout to a Drupal form, but the form.html.twig has only the “children” variable by default, which holds rendered markup.

      In order to make single form components available in the Twig template, you have to use hook_theme().

      Firstly, thanks to Ruslan Piskarov, whose article pushed me in the right direction: https://makedrupaleasy.com/articles/drupal-10-how-render-any-form-twig-template

      As an example, I use the Drupal Commerce „Cart Form“, which basically holds all contents on the cart page (views_form_commerce_cart_form_default).

      In your THEMENAME.theme file, add hook_theme() like so:

      /**
       * Implements hook_theme().
       */
      function drowl_child_theme($existing, $type, $theme, $path) {
        return [
          'views_form_commerce_cart_form_default' => [
            'render element' => 'form',
            'path' => $path . '/templates/commerce/cart',
          ],
        ];
      }
      

      ‚views_form_commerce_cart_form_default‘ needs to be your BASE_FORM_ID.

      The ‚render element‘ is the name of the render array variable.

      The path is optional, if you are fine with putting the template right into your „templates“ folder.

      In this example, the resulting Twig file needs to be /templates/commerce/cart/views-form-commerce-cart-form-default.html.twig.

      The template looks like this:

      {#
      /**
        * @file
        * Default theme implementation for a 'form' element.
        *
        * Available variables
        * - attributes: A list of HTML attributes for the wrapper element.
        * - children: The child elements of the form.
        *
        * @see template_preprocess_form()
        *
        * @ingroup themeable
        */
      #}
      
      {# {{ dump(form) }} #}
      <div class="commerce-cart">
        <form{{ attributes }}>
          <div class="row">
            <div class="col col-md-8">
              <div class="commerce-cart__line-item-box">
                {{ form|without(
                  'footer',
                  'actions',
                  'paypal_smart_payment_buttons'
                ) }}
              </div>
            </div>
            <div class="col col-md-4 commerce-cart__actions-sum">
              {{ form.actions }}
              <a href="/" class="btn btn-outline-dark btn--block">{{ 'Products Overview'|t }}</a>
              {{ form.paypal_smart_payment_buttons }}
              {{ form.footer }}
            </div>
          </div>
        </form>
      </div>
      

      Thats it, happy coding!

      Fork Awesome Icomoon Package

      I’ve invested some time to create a Icomoon.io Package of Fork Awesome, based on the broken SVG icons from the current Fork Awesome release (1.2.0). I have basically resized and centered them, to fit the canvas size, so some icon sizes might be not perfect.

      Fork Awesome 1.2.0 · A fork of Font Awesome, originally created by Dave Gandy, now maintained by a community. Fork Awesome is licensed under SIL OFL 1.1· Code is licensed under MIT License. Documentation is licensed under CC BY 3.0.

        JTL Shop (5) – Print Linkgroups in Smarty

        Nova has two simple snippets to print (custom) linkgroups, this snippet prints out list items without the list wrapper.

        Link List with toggable submenus (like the regular sidebar menus)

        {include file='snippets/linkgroup_recursive.tpl' linkgroupIdentifier='LINKGROUP_TEMPLATE_NAME' dropdownSupport=BOOL}

        Link List with dropdown submenus (like the regular top-bar menu)

        {include file='snippets/linkgroup_list.tpl' linkgroupIdentifier='LINKGROUP_TEMPLATE_NAME' dropdownSupport=BOOL}

        To print out the links on your own, check out the code of those snippet templates.

          Extend a Module Library in a Module (like libraries-extend in Themes)

          Motorcycly with fully packed trailer

          In Drupal Themes its very easy to extend existing libraries using the themes .info (and .libraries) file. This ain’t possible in a Mobule .info file. So we need a hook to do this:

          /**
           * Implements hook_library_info_alter()
           * - Extend some module libraries we support or require for MY_MODULE
           */
          function MY_MODULE_library_info_alter(&$libraries, $extension) {
            if ($extension == 'views_bulk_operations' && isset($libraries['frontUi'])) {
              // Extend existing library views_bulk_operations/adminUi
              // Important! That a library is listed by this hook, doesn't mean the library is attached, it just means its registered.
              $libraries['frontUi']['dependencies'][] = 'MY_MODULE/MY_LIBRARY_NAME';
            }
          }

            Wrong background-size for SVG-Background image in Firefox

            Not the first time i ran into problems with SVGs preserveAspectRatio attribute, but i can’t remember a case where Firefox handled this different from Chrome. However, lets have look at the this weird behavoir.

            The goal was to build a very flexible lines-background-element with CSS-Grid:

            Chrome result without preserveAspectRatio=“false“ on the SVG-Wrapper

            While Chrome renders everything perfectly fine, Firefox produced this:

            Firefox result without preserveAspectRatio=“false“ on the SVG-Wrapper

            The Code:

            HTML

                <div class="line-bg line-bg--middle-center-to-bottom-right">
                  <div class="line-bg__item line-bg__item--curve-tl"></div>
                  <div class="line-bg__item line-bg__item--flex-h"></div>
                  <div class="line-bg__item line-bg__item--flex-v"></div>
                </div>

            CSS

                .line-bg{
                  --line-edge-group-size: 268px;
                  --line-group-size: calc(var(--line-edge-group-size) * 0.5522);
                  position:absolute;
                  left:50%;
                  top:50%;
                  right:0;
                  bottom:0;
                  display:grid;
                  grid-template-columns: var(--line-edge-group-size) auto;
                  grid-template-rows: var(--line-edge-group-size) auto;
                }
                .line-bg__item--flex-v{
                  background-image: url('line_bg_v.svg');
                  background-repeat: repeat-y;
                  background-position:0 0;
                  background-size: var(--line-group-size) auto;
                }

            SVG (the *wrong* code)

            <?xml version="1.0" encoding="utf-8"?>
            <svg viewBox="0 0 690 25" xmlns="http://www.w3.org/2000/svg">
              <g transform="matrix(1, 0, 0, 0.961538, 0, 0)">
                <path d="M676.115,-0L676.115,26L690.031,26L690.031,-0L676.115,-0ZM507.101,-0L507.101,26L521.018,26L521.018,-0L507.101,-0ZM338.083,-0L338.083,26L352.004,26L352.004,-0L338.083,-0ZM169.069,-0L169.069,26L182.986,26L182.986,-0L169.069,-0ZM13.916,-0L0,-0L0,26L13.916,26L13.916,-0Z" style="fill:#878787;fill-rule:nonzero;"/>
              </g>
            </svg>
            

            So after testing around, with the background-size, -position, etc. the conclusion was that the SVG itself must be the problem. And it kinda was, but i’im pretty sure its a Firefox Bug with SVG + background-size. As you can see in the code, i was not trying to change the aspect-ratio in any way, i just set a fixed with + auto height for the background and let em repeat verticaly, so the preserveAspectRatio shouldn’t needed here.

            The Workaround

            <?xml version="1.0" encoding="utf-8"?>
            <svg viewBox="0 0 690 25" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
              <g transform="matrix(1, 0, 0, 0.961538, 0, 0)">
                <path d="M676.115,-0L676.115,26L690.031,26L690.031,-0L676.115,-0ZM507.101,-0L507.101,26L521.018,26L521.018,-0L507.101,-0ZM338.083,-0L338.083,26L352.004,26L352.004,-0L338.083,-0ZM169.069,-0L169.069,26L182.986,26L182.986,-0L169.069,-0ZM13.916,-0L0,-0L0,26L13.916,26L13.916,-0Z" style="fill:#878787;fill-rule:nonzero;"/>
              </g>
            </svg>
            

            Set preserveAspectRatio=“none“ on the SVG wrapper. Done.