Search code examples
javascripthtmlcsstwitter

Tweet button doesn't appear when used in accordion with some browsers


I'm using the following code to display a twitter button to share a page from one website.

<script>$(document).ready(function(){!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");});</script>

<a href="https://twitter.com/share" class="twitter-share-button" data-url="/myUrl" data-text="message" data-hashtags="myhashtag">Tweet</a>

This code is working with no problem when used in a page, no matter the browser I'm using.

Now my problem begins when I want to put that button in an html accordion. When the element is placed in something that is hidden at first the CSS behaves differently depending on the browser. On Chrome most of the time the tweet button is displayed when expanding the accordion. While on Internet Explorer and Firefox (I have not Edge to test it) the button is computed with size of 1px. If I use the developer tools to set correct sizes for the button in the CSS then it appears. The javascript does it's job : script is loaded and the iframe is here with all the necessary code, I have no problem with the load from the twitter website, my only problem is with the computed CSS that prevent the display of the button.

So I'm looking for help to display the button even if it is hidden at start.

Edit : The below snippet is an attempt to demonstrate my problem.

.btn-o {
    width: 100% !important;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script>$(document).ready(function(){!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");});</script>
<p>
Tweet button not hidden at start
<a href="https://twitter.com/share" class="twitter-share-button" data-url="/myUrl" data-text="message" data-hashtags="myhashtag">Tweet</a>
</p>
<p>
Tweet button hidden at start

<div id="accordion">
  <div class="card">
    <div class="card-header" id="headingOne">
      <h5 class="mb-0">
        <button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
          Collapsible Group Item #1
        </button>
      </h5>
    </div>

    <div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
      <div class="card-body">
        Here is also a tweet button, if you see nothing you have my bug demonstrated (don't work with IE or Firefox most of the time)
        <a href="https://twitter.com/share" class="twitter-share-button" data-url="/myUrl" data-text="message" data-hashtags="myhashtag">Tweet</a>
      </div>
    </div>
  </div>
</div>

</p>
</div>


Solution

  • Ok here is the solution I've managed to get it working and the explanation :

    First explanation : twitter looks for the twitter-share-button to insert one iframe. Unfortunately if the content isn't visible then the size of the iframe will be 1.

    Second manage the error : I had to add an event on my hidden content in order to handle the cases when the generated twitter iframe has a size of 1. So the idea is to add a new button and reload the twitter widget in order to replace the link by the iframe when the content is visible (we do that with twttr.widgets.load();). We also need to do that only once not each time that's why I've added one check on the iframe width before inserting content and reloading the widget.

    $(".card").on('click',function(){
    var width=0;
    // calculates largest width for the iframe
    $('#collapseOne').find('.card-body').find('iframe').each(function(){if (width < $(this).width()) {width=$(this).width()}});
    // we do the following only if there is no larger iframe for the tweet button
    // otherwise there is a risk to insert more than one button in the page
    if(width < 2) {
    $('#collapseOne').find('.card-body').append('<a href="https://twitter.com/share" class="twitter-share-button" data-url="/myUrl" data-text="message" data-hashtags="myhashtag">Tweet</a>');
    twttr.widgets.load();
    }
    });
    

    Thanks to @misorude for suggesting the community post and to this post Re-render Tweet button via JS that helped me to reload the twitter widget.