Bootstrap: Simplify the customization of popover

Created on 5 Mar 2016  路  4Comments  路  Source: twbs/bootstrap

This is a suggestion I have from a long time. I thought it was missing in version 3, and it might be well to allow it in version 4.
When we want to customize the popover (width, content padding...) we actually do not have other choice that to redefine the full template, which is not very readable, maintainable and evolutive.
A better option might be to allow to add a class to the popver, so we could add our custom styles to this class without impacting all the popovers.

Example :

.popover-custom .popover-content {
  padding: 0;
}

$('#foo').popover({
  title: ...,
  content: ...,
  class: 'popover-custom'
});
feature has-pr help wanted js v4 v5

Most helpful comment

What @fredgate proposes would be a pretty straightforward addition to the Tooltip.prototype.tip function in tooltip.js.

For example:

  Tooltip.prototype.tip = function () {
    if (!this.$tip) {
      this.$tip = $(this.options.template)

      // New className handling
      if(this.options.className) {
        this.$tip.addClass(this.options.className);
      }

      if (this.$tip.length != 1) {
        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
      }
    }
    return this.$tip
  }

Not a huge change but I wonder if the root issue can be solved simply with more visible documentation of the .tip function in general.

I think any scenario can be covered using .tip() (please correct me if i'm wrong, I might not be considering all scenarios)

Single Use

  $('#my-popover').popover()
    .data('bs.popover')
    .tip()
    .addClass('my-class-name');

Multiple Matching Selectors

  $('.my-popovers').popover()
    .map(function(){
      $(this).data('bs.popover')
        .tip()
        .addClass('my-class-name')
    });

All 4 comments

I'm not sure what you're suggesting. Perhaps you could post a JSFiddle/JSBin of this in action?

I second this.

Take a look at the myriad answers to this question on stack overflow to get a sense for how often it comes up and what kinds of workarounds people are resorting to: http://stackoverflow.com/questions/12170357/dynamically-add-a-class-to-bootstraps-popover-container

If I want to style a specific popover, I have several possible approaches:

  1. If I don't specify the popover's container, it's created adjacent to the target element. This gives me access to the popover from css via .target + .popover, but it also constrains the popover in some possibly breaking ways (e.g. overflow: hidden on an ancestor.) These things are annoying to work around in css.
  2. If I specify container: "body", it's appended to the <body>. This fixes the css problems inherent to the previous approach, but cripples my ability to style that specific popover from css.
  3. If I append a custom container to the body, I could use it via container: "#custom-container". This gives me access via #custom-container .popover, but has the downside of littering my base template with cruft like <div id="custom-container"></div>.
  4. If I append it to the body and specify a custom template, I may use .class-from-custom-template, but the custom template is a hunk of HTML I'd rather avoid writing if I can. The only interesting part of that template would be the class, and that's unclear when confronted with the entire template.
  5. I may resort to attaching the class from javascript, but that makes it hard to initialize popovers generically with a construct such as $('.has-popover').popover().

In the current state of things, I think the best solution is combining the 5th approach with some code that copies something like data-class from the target to the popover.

What @fredgate proposes would be a pretty straightforward addition to the Tooltip.prototype.tip function in tooltip.js.

For example:

  Tooltip.prototype.tip = function () {
    if (!this.$tip) {
      this.$tip = $(this.options.template)

      // New className handling
      if(this.options.className) {
        this.$tip.addClass(this.options.className);
      }

      if (this.$tip.length != 1) {
        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
      }
    }
    return this.$tip
  }

Not a huge change but I wonder if the root issue can be solved simply with more visible documentation of the .tip function in general.

I think any scenario can be covered using .tip() (please correct me if i'm wrong, I might not be considering all scenarios)

Single Use

  $('#my-popover').popover()
    .data('bs.popover')
    .tip()
    .addClass('my-class-name');

Multiple Matching Selectors

  $('.my-popovers').popover()
    .map(function(){
      $(this).data('bs.popover')
        .tip()
        .addClass('my-class-name')
    });

Was this ever addressed in V4? I've wanted a fix for this too and it seems like it could be done pretty quickly.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bellwood picture bellwood  路  3Comments

athimannil picture athimannil  路  3Comments

matsava picture matsava  路  3Comments

ghost picture ghost  路  3Comments

tiendq picture tiendq  路  3Comments