Please integrate ability to use Bootstrap classes

Created on 28 May 2025, 2 months ago

Problem/Motivation

To be able to use theme CSS classes for layout.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

Would like fields to add classes or selectors to be able to change all aspects of the layout using Bootstrap variables. This could include padding, margin, color, justification, etc. Potential to have these fields available for all fields. Text, color, button. and even the wrapper .ept-hero-container.

thank you

API changes

Data model changes

✨ Feature request
Status

Active

Version

1.4

Component

User interface

Created by

πŸ‡ΊπŸ‡ΈUnited States gmarez8

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @gmarez8
  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Hi gmarez8, you can install Fences module:
    https://www.drupal.org/project/fences β†’
    It allows to add additional classes for all fields wrappers.

    I have additional module for Bootstrap Buttons:
    https://www.drupal.org/project/ept_bootstrap_button β†’

    Here is a bunch of Bootstrap Paragraphs:
    https://www.drupal.org/project/drowl_paragraphs_bs β†’

    I'm not sure what exactly you want to do with additional classes. All EPT paragraphs has or can have Additional Classes setting. It's possible to extend Field Widget for EPT Settings field and add any number of additional fields. But then it will look too messy for editors.

    If you could specify what exactly want to extand with classes (First, Second buttons) then I will extend Hero Field Widget for EPT settings field.

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Feel free to re-open this ticket if will need any help with extending Field Widget.

  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Hi Lev,

    It looks like Fences only gives the option to wrap fields in the drupal config side. This would not seem to give the flexibility that I would like. For example, using the EPT hero, one page might have a dark themed hero, another might have light, or even bootstrap theme colors. If there was a class field in the page editor we could simply apply these styles with classes. or a custom select field that we could populate these values would be good.

    Drowl requires Radix. I am using Barrio Bootstrap.

    The bootstrap button is not implemented in EPT Hero.

    Thank you

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    I see what you mean, usually on commercial project, I use different predefined variants. I create predefined styles and separate them with View Modes, then you need to create own template for each view mode with all needed classes. It's possible to choose view mode and edit page using Paragraph View Mode or Paragraphs View Modes modules:
    https://www.drupal.org/project/paragraph_view_mode β†’
    https://www.drupal.org/project/paragraphs_viewmode β†’

    Here is article about overriding EPT templates:
    https://www.drupal.org/project/ept_slideshow/issues/3406887 πŸ’¬ How to override slideshow item template file? Fixed

    Then you don't need to select 15 classes on edit form and select only Variant (predefined View Mode). It looks harder to implement and create content. But if you will see from Content Editor perspective, it's easier to select Variant instead of remembering Bootstrap Grid classes. It's easier to switch from Bootstrap to Tailwind or own Desing System when all classses are stored in templates than go through all pages and change classes manually.

    In the case you have only 20-30 pages and you need to create dozens of these sites quickly and you will create pages by yourself. This approach with fields for all elements will work. I agree it's worth it then. OK, let's try to achieve this. I will add collapsed fieldset with textfields for additional classes and pass them in the template:

        <div class="bg-inner {{ bg_inner_classes }}"></div>
        <div class="ept-container {{ ept_container_classes }}">
  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia
  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Hi gmarez8, I added fields for all wrappers in 'Elements additional classes' fieldset:

    You can update module and use bootstrap classes for the wrappers:
    https://www.drupal.org/project/ept_hero/releases/1.4.6 β†’

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia
  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia
  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Lev, this is a wonderful addition! Thank you so much for adding this. I was trying to get my own module created using multiple background images (some of them being linear and radial gradients) but it was not working. It looks like now I can create a series of classes to apply much of those styles this way. Gradients might be tricky with CSS ordering, if it's even possible, but I will give it a shot.

    Thank you again!

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Hey gmarez8, it's not tricky to generate CSS at all, you can check how DOM Box and Background color work and you can extend Field Widget with any fields with Drupal Form API. You get values from Drupal Form API and insert them in template preprocess and output in template as variable. A little bit messy, but when where will be a lot of code I will refactore it with plugins. For now it's OK to do it straightforward in functional way.

    I can add these fields as well and make configuration form to enable this functionality in EPT Core if it's needed on site:
    https://www.drupal.org/project/ept_core β†’
    It's not hard to implement gradient generator like this:
    https://www.w3schools.com/colors/colors_gradient.asp

    Or find jquery/javascript library for generating gradient and include it with EPT Core.

    Also, as an option, you can add Custom CSS field, generate gradient on another service and insert it:
    https://cssgradient.io/

  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Thanks Lev, I have worked up a bunch of SASS mixins to generate some complex gradients using classes>
    class="gradient-radial circle bgsize-farthest-corner gradient-sunset blend-screen"
    I should just be able to drop them into the fields you made. It's pretty flexible!

    The only downside to this is that the person creating the page would need to know it's possible since there is nothing in the UI to indicate how it can be done. Best I can do is train staff on it's usage, unless it's also possible to create custom list string fields to populate each variable for each repeatable BG image.

    A guy can dream, but this works for now :)

    THANK YOU!

  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Hi again, dunno if it helps because your code is structured very differently, but here is the twig file I generated. It never installed properly for me to be able to test, but it looks like it could have worked.

    {#
      Bootstrap Hero
    #}
    
    {% set container_class = paragraph.field_container_class.value ?? '' %}
    {% set headline_class = paragraph.field_headline_class.value ?? '' %}
    {% set subheadline_class = paragraph.field_subheadline_class.value ?? '' %}
    {% set body_class = paragraph.field_body_class.value ?? '' %}
    {% set button_class = paragraph.field_button_class.value ?? '' %}
    
    {# Gradient Builder #}
    {% set gradient_type = paragraph.field_gradient_type.value ?? '' %}
    {% set gradient_angle = paragraph.field_gradient_angle.value ?? '' %}
    {% set stops = [] %}
    {% for stop in paragraph.field_gradient_stops %}
      {# Access nested paragraph fields #}
      {% set color = stop.entity.field_stop_color.color|default('#000000') %}
      {% set pos = stop.entity.field_stop_position.value|default('') %}
      {% if pos %}
        {% set stops = stops|merge([color ~ ' ' ~ pos ~ '%']) %}
      {% else %}
        {% set stops = stops|merge([color]) %}
      {% endif %}
    {% endfor %}
    {% set gradient_css = '' %}
    {% if gradient_type and stops|length > 0 %}
      {% if gradient_type == 'linear' %}
        {% set gradient_css = 'linear-gradient(' ~ (gradient_angle ?: '180deg') ~ ', ' ~ stops|join(', ') ~ ')' %}
      {% else %}
        {% set gradient_css = 'radial-gradient(' ~ (gradient_angle ?: 'ellipse at center') ~ ', ' ~ stops|join(', ') ~ ')' %}
      {% endif %}
    {% endif %}
    
    {# Multiple Background Images #}
    {% set bg_images = [] %}
    {% for media in paragraph.field_background_images %}
      {% if media.entity.field_media_image.entity.uri.value %}
        {% set bg_images = bg_images|merge(['url(' ~ file_url(media.entity.field_media_image.entity.uri.value) ~ ')']) %}
      {% endif %}
    {% endfor %}
    
    {% set background_style = '' %}
    {% if gradient_css or bg_images|length > 0 %}
      {% set backgrounds = [] %}
      {% if gradient_css %}
        {% set backgrounds = backgrounds|merge([gradient_css]) %}
      {% endif %}
      {% if bg_images|length > 0 %}
        {% set backgrounds = backgrounds|merge(bg_images) %}
      {% endif %}
      {% set background_style = 'background-image: ' ~ backgrounds|join(', ') ~ ';' %}
    {% endif %}
    
    <section class="hero {{ container_class }}" style="{{ background_style }}">
      {% if paragraph.field_headline.value %}
      {% set headline_tag = paragraph.field_headline_tag.value|default('h2') %}
        <{{ headline_tag }} class="{{ headline_class }}">{{ paragraph.field_headline.value }}</{{ headline_tag }}>
      {% endif %}
      {% if paragraph.field_subheadline.value %}
        <h2 class="{{ subheadline_class }}">{{ paragraph.field_subheadline.value }}</h2>
      {% endif %}
      {% if paragraph.field_body.value %}
        <div class="{{ body_class }}">{{ paragraph.field_body.value }}</div>
      {% endif %}
      {% if paragraph.field_button_label.value and paragraph.field_button_url.uri %}
        <a href="{{ paragraph.field_button_url.uri }}" class="btn {{ button_class }}">
          {{ paragraph.field_button_label.value }}
        </a>
      {% endif %}
  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Hi Lev,

    I added classes to the hero wrapper and dashes were added in between each class.

    entered: gradient-radial ellipse bgsize-80-40 gradient-rainbow alpha-70
    rendered: class="ept-container gradient-radial-ellipse-bgsize-80-40-gradient-rainbow-alpha-70"

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Ough..., sorry, I forgot to test multiple classes. I removed twig |clean_class filter, because we have class validation in edit form. So it must be fine now.
    https://www.drupal.org/project/ept_hero/releases/1.4.7 β†’

  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Hi Lev,

    Thanks for making the fix. I have added a class to the button and cleared fields with previous values. There seems to still be a style tag in the html filled with the old values. This is overriding the bootstrap classes that I am trying to use. Is there a way to clear this or make it so styles are only placed inline if there is info in the settings?

    Thanks again for all your help!

  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    ept-basic-button class is needed for styling buttons. There is only way to override template in your custom theme/module:
    https://www.drupal.org/project/ept_slideshow/issues/3406887#comment-1568... πŸ’¬ How to override slideshow item template file? Fixed

    Create a new template:
    paragraph--ept-hero--default--custom.html.twig

    And copy content from paragraph--ept-hero--default.html.twig template. Then you will be able to remove default classes there.

  • πŸ‡ΊπŸ‡ΈUnited States gmarez8

    Thank you Lev! I used that idea to import the ept_bootstrap_button instead. Works like a charm!

Production build 0.71.5 2024