web-dev-qa-db-fra.com

Comment puis-je redimensionner automatiquement la largeur du bouton Facebook Like?

J'implémente le Facebook Like Button , mais je rencontre des problèmes avec la largeur. J'utilise l'implémentation du SDK JavaScript, pas l'iframe direct.

Selon la documentation, la largeur par défaut est 450. C'est très bien, et je comprends que la largeur peut être modifiée au moyen de l'attribut width sur le <fb:like> tag. Cependant, mon problème est que je ne peux vraiment pas spécifier une largeur fixe. En raison de la nature du bouton, la largeur n'est pas constante dans tous les états. Par exemple, si personne n'a encore aimé la page, celle-ci affiche "Soyez le premier de vos amis à aimer ça"; si quelqu'un l'a, il affiche "XXX personnes comme ça. Soyez le premier de vos amis"; et toujours si vous l'aimez, il affiche "Vous aimez ça" ou "Vous et XXX personnes aimez ça." En d'autres termes, il existe de nombreux états du bouton, dont aucun ne partage une largeur constante.

Ce ne serait pas vraiment un problème si je n'avais pas voulu afficher le bouton flottant sur le côté droit d'un <div>. Pour être plus clair, voici ce que je fais:

<div id="wrapper">
    <span class="fb-like"><fb:like show_faces="false" width="450" font="lucida grande""></fb:like></span>
    ...
</div>
<style type="text/css">
.fblike {
    display: inline-block;
    padding: 0.5em;
    position: absolute;
    right: 0;
    top: 0;
}
#wrapper {
    position: relative;
}
</style>

Cela fonctionne très bien, mais le problème est que l'iframe a maintenant une largeur constante de 450 pixels. Étant donné que l'iframe est aligné à gauche, lorsque le texte est plus court, il y a un espace supplémentaire à droite. J'ai essayé diverses applications de text-align: right en vain. Et le problème est encore aggravé par le fait qu'il ne s'agit que d'un balisage de fantaisie pour une iframe ajoutée par le FB SDK, donc je suis impuissant à modifier son contenu avec CSS ou JavaScript.

J'ai besoin d'une solution qui soit (a) maintiendra la largeur de la zone du bouton dynamique (c'est-à-dire qu'elle change en fonction du contenu); ou (b) aligner tout à droite dans la zone des boutons.

Merci pour toute aide que n'importe qui peut me donner!

31
Josh Leitzel
#fblike iframe {
    width: 95px !important;
}

#fblike .fb_Edge_comment_widget iframe {
    width: 330px !important;
}

Et

<div id="fblike"><fb:like show-faces="false" layout="button_count"></fb:like></div>

De cette façon, les iframes de bouton de commentaire et d'aimant sont de largeur fixe. Pas d'effets drôles. J'espère que ça aide.

12
Andrius Paulauskas

Comme tout le monde le sait probablement maintenant, il n'y a pas de moyen facile de le faire. Cependant, j'ai trouvé une sorte de complicité programmatique. Et quand je dis kludge, je le pense vraiment! Je ne pense pas que cela soit prêt pour les heures de grande écoute, mais quelqu'un peut aimer bricoler le concept et essayer de trouver quelque chose de réalisable.

L'idée est que bien que vous ne puissiez pas lire la largeur du contenu de l'iframe, vous pouvez parcourir une série de largeurs pour l'iframe lui-même jusqu'à ce que vous en trouviez une qui empêche à peine le texte à l'intérieur de s'habiller. À ce stade, le texte doit toucher le côté droit de l'iframe. En d'autres termes, nous voulons définir la largeur de l'iframe à 1px plus large que la largeur qui ferait en sorte que le texte s'habille.

En principe, il est assez facile de détecter si le texte est enveloppé: vous définissez la largeur de l'iframe, attendez que le code FB ajuste le contenu, puis lisez la hauteur. Si tout tient sur une seule ligne, la hauteur doit être d'environ 25 pixels. Plus que cela signifie que le texte est bouclé.

La difficulté vient de la partie "attendre le code FB pour ajuster le contenu". J'ai l'impression qu'il doit y avoir un moyen de forcer un "redessin" de l'iframe, mais jusqu'à présent je ne l'ai pas trouvé. Appeler FB.XFBML.parse () est évident, mais cela ne semble pas fonctionner. C'est la partie où je suis resté coincé. Je force l'iframe à se recharger en définissant son attribut src, qui fait le travail mais à un prix horrible en vitesse. À ce stade, il s'agit simplement d'une "preuve de concept". Presque aussi bon serait un moyen simple de savoir quand un redessin a été terminé; Je pense que cela devrait également être possible, mais mon cerveau s'est enlisé avant de trouver quelque chose de simple.

Quoi qu'il en soit, voici un code de test si vous voulez l'essayer. Il faut une éternité pour mettre le bouton en position, mais cela fonctionne au moins. J'ai laissé tout visible pendant le processus de chargement afin que vous puissiez voir ce qu'il fait, sur une vraie page, il serait préférable de garder les choses cachées jusqu'à ce que tout soit prêt. Notez également que l'alignement peut être légèrement décalé car j'ajuste la largeur de 5 pixels à la fois. Si les choses pouvaient être accélérées, il serait facile d'utiliser à la place 1px. Encore mieux serait probablement un ajustement approximatif pour se rapprocher, puis un ajustement fin pour le rendre parfait. De toute évidence, beaucoup d'expérimentation à faire, pour quiconque voudra en profiter.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var likediv, likeframe;
function loadcode(d, s, id)
{
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) {return;}
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width='225px';
setTimeout(shrink, 10);
}
function shrink()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
var currwidth=parseInt(likeframe.style.width);
if (currwidth>=500) return;
newwidth=currwidth+5;
likeframe.style.width=newwidth+'px';
likeframe.style.height='0';
likeframe.src=likeframe.src;
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) setTimeout(checkframe, 10);
else if (h>25) shrink();
//else we are done; make the frame visible if we hid it earlier
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>

EDIT: A fait un peu plus d'expérimentation, toujours une solution de contournement maladroite mais plus rapide qu'auparavant:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var likediv, likeframe, targwidth;
function loadcode(d, s, id)
{
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) {return;}
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width='225px';
setTimeout(shrink, 10);
}
function shrink()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
var currwidth=parseInt(likeframe.style.width);
if (currwidth>=500) return;
targwidth=currwidth+5;
likeframe.style.width='10px';
likeframe.style.height='0';
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe, 10); return; }
likeframe.style.width=targwidth+'px';
likeframe.style.height='0';
setTimeout(checkframe2, 10);
}
function checkframe2()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) setTimeout(checkframe2, 10);
else if (h>25) shrink();
//else we are done; make the frame visible if we hid it earlier
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>

MODIFICATION FINALE: C'est le meilleur que je pense que cette méthode obtiendra jamais; le code pourrait certainement être modifié, mais il faudra toujours plusieurs secondes pour parcourir les largeurs d'essai pour trouver ce qui fonctionne. Mais c'est maintenant assez rapide (environ 5 secondes) pour qu'il soit réellement utilisable. BTW J'ajoute chaque nouvelle version de code plutôt que de remplacer les anciennes parce que je n'ai pas fait beaucoup de tests inter-navigateurs de ce code et il est possible que les versions plus rapides ne fonctionnent pas pour quelqu'un. Puisqu'il s'agit uniquement de code expérimental, je pense qu'il vaut mieux avoir les différentes versions disponibles pour le repli.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var minwidth=225, maxwidth=500, finished=false, last_was_good=null;
var likediv, likeframe, targwidth, boundlow, boundhigh;
function loadcode(d, s, id)
{
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) {return;}
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width=minwidth+'px';
setTimeout(trynewwidth, 1);
}
function trynewwidth()
{
if (last_was_good==null) { boundlow=minwidth; boundhigh=maxwidth; }
else if (last_was_good) boundhigh=targwidth;
else boundlow=targwidth;
finished=((boundhigh-boundlow)<2);
if (finished && last_was_good) { done(); return; }
if (finished && !last_was_good) targwidth=boundhigh;
else targwidth=parseInt((boundlow+boundhigh)/2);
setTimeout(setwidth, 1);
}
function done()
{
//All finished, if we were hiding the div make it visible now
}
function setwidth()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
likeframe.style.width='10px';
likeframe.style.height='0';
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe, 10); return; }
likeframe.style.width=targwidth+'px';
likeframe.style.height='0';
setTimeout(checkframe2, 10);
}
function checkframe2()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe2, 10); return; }
if (finished) { done(); return; }
last_was_good=(h<26);
setTimeout(trynewwidth, 1);
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>
5
Floyd Wilburn

Si vous utilisez la version XFBML du bouton J'aime, ainsi que le SDK Facebook Javascript, vous pouvez vous abonner à l'événement 'xfbml.render', et une fois que cet événement se déclenche, vous pouvez définir la largeur du bouton similaire iframe à une petite valeur . (J'utilise 50px.) L'iframe ajustera alors automatiquement sa largeur selon les besoins afin d'afficher le bouton et le nombre et comme tous les autres éléments, selon votre configuration.

https://developers.facebook.com/docs/reference/javascript/

Le plus grand obstacle à cette solution est que vous aurez besoin d'un identifiant d'application Facebook. Vous pouvez obtenir un ID d'application en créant une application ici: https://developers.facebook.com/apps/

5
Pascal

Il y a des réponses FAQ qui valent la peine d'être lues lors du choix d'une taille.

https://developers.facebook.com/docs/plugins/like-button

Bien que cela soit dit, c'est toujours assez cryptique:

"La largeur du plugin. La disposition que vous choisissez affecte les largeurs minimum et par défaut que vous pouvez utiliser, veuillez consulter le FAQ ci-dessous pour plus de détails."

la norme

Largeur minimale: 225 pixels.

Le minimum augmente de 40 pixels si l'action est "recommandée" par et augmente de 60 pixels si l'envoi est "vrai".

Largeur par défaut: 450 pixels. Hauteur: 35 pixels (sans photos) ou 80 pixels (avec photos).

box_count

Largeur minimale: 55 pixels. Largeur par défaut: 55 pixels. Hauteur: 65 pixels.

button_count

Largeur minimale: 90 pixels. Largeur par défaut: 90 pixels. Hauteur: 20 pixels.

bouton

Largeur minimale: 47 pixels. Largeur par défaut: 47 pixels. Hauteur: 20 pixels.

2
Simon_Weaver

J'utilise personnellement les éléments suivants ...

#fbook-like {
    width: 50px !important; /*width of just the button*/
    overflow: visible; /*so there is no cut off*/
    vertical-align: top; /*bc all other like buttons align top*/
}

Ce que j'ai fait ici est de mettre le bouton fb à l'extrême droite et donc il s'aligne avec mon Edge, et seuls les commentaires ajoutés (dynamiques en largeur) s'afficheront après le Edge. Je peux garder un bon design tout en faisant apparaître les commentaires, quelle que soit la longueur.

2
Jacob Thomason

Correction CSS

.fb-like, 
.fb-like > span,
.fb-like > span iframe {
    max-width:273px;
}
2
Tym3k

J'ai ajouté ceci à mon CSS:

div.fb-like.fb_iframe_widget > span {
 width: 100% !important;
}

div.fb-like.fb_iframe_widget{
 width: 100%;
}
0
patrick

J'ai dû faire face à ce même problème avec le plugin add-this et résolu de manière similaire:

.addthis_button_facebook_like,
.addthis_button_facebook_like span,
.addthis_button_facebook_like span iframe {
    max-width: 450px !important;
}
0
poppero