Как сделать так, чтобы ширина кнопки «Нравится» на Facebook автоматически изменялась?

Я внедряю кнопку "Мне нравится" в Facebook, но у меня возникают проблемы с шириной. Я использую реализацию JavaScript SDK, а не прямой iframe.

Согласно документации, ширина по умолчанию равна 450. Это нормально, и я понимаю, что ширину можно изменить с помощью атрибута width в теге <fb:like>. Однако моя проблема в том, что я действительно не могу указать фиксированную ширину. Из-за особенностей кнопки ширина не является постоянной во всех состояниях. Например, если страница еще никому не понравилась, на ней отображается «Будьте первым из ваших друзей, кому это понравится»; если у кого-то есть, выводит "ХХ людей нравится это. Будь первым в друзьях"; и тем не менее, если вам это понравилось, отображается "Вам нравится это" или "Вам и XXX людям это нравится". Другими словами, существует множество состояний кнопки, ни одно из которых не имеет постоянной ширины.

Это не было бы большой проблемой, если бы не тот факт, что я хочу отобразить кнопку, плавающую справа от <div>. Чтобы было понятнее, вот что я делаю:

<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>

Это прекрасно работает, но проблема в том, что iframe теперь имеет постоянную ширину 450 пикселей. Поскольку iframe выровнен по левому краю, когда текст короче, справа остается дополнительное пространство. Я пробовал различные приложения text-align: right безрезультатно. И проблема усугубляется еще и тем фактом, что на самом деле это просто причудливая разметка для iframe, добавляемого FB SDK, поэтому я бессилен изменить какое-либо его содержимое с помощью CSS или JavaScript.

Мне нужно решение, которое либо (а) сохранит динамическую ширину области кнопки (т. е. она будет меняться в зависимости от содержимого); или (b) выровняйте по правому краю все в области кнопки.

Спасибо за любую помощь, кто может мне помочь!


person Josh Leitzel    schedule 03.12.2010    source источник


Ответы (8)


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

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

И

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

Таким образом, как комментарии, так и фреймы лайков имеют фиксированную ширину. Никаких забавных эффектов. Надеюсь, поможет.

person Andrius Paulauskas    schedule 28.01.2011
comment
На самом деле это только изменяет размер iframe, но все же обрезает некоторый текст внутри него, поскольку некоторые из более глубоких тегов внутри iframe по-прежнему имеют назначения ширины CSS, которые вы не можете изменить за пределами документа. - person i--; 23.02.2013

Как все, вероятно, уже знают, нет простого способа сделать это. Однако я придумал своего рода программный кладж. И когда я говорю кладж, я действительно имею это в виду! Я не считаю это готовым для прайм-тайма, но кому-то может понравиться повозиться с концепцией и попытаться найти что-то работоспособное.

Идея состоит в том, что, хотя вы не можете прочитать ширину содержимого iframe, вы можете перебрать серию значений ширины для самого iframe, пока не найдете тот, который едва предотвращает перенос текста внутри. В этот момент текст должен касаться правой стороны iframe. Другими словами, мы хотим установить ширину iframe на 1 пиксель шире, чем ширина, при которой текст будет обтекаться.

Определить, переносится ли текст, в принципе достаточно просто — вы устанавливаете ширину iframe, ждете, пока код FB отрегулирует содержимое, а затем считываете высоту. Если все помещается в одну строку, высота должна быть около 25 пикселей. Более того, это означает, что текст завернут.

Трудность связана с частью «подождите, пока код FB настроит контент». Я чувствую, что должен быть какой-то способ принудительно «перерисовать» iframe, но пока я его не нашел. Вызов FB.XFBML.parse() очевиден, но, похоже, он не работает. Это та часть, где я застрял. Я заставляю iframe перезагружаться, устанавливая его атрибут src, который выполняет свою работу, но с ужасной ценой скорости. На данный момент это просто означает «доказательство концепции». Почти таким же хорошим был бы простой способ узнать, когда любая перерисовка завершена; Я чувствую, что это тоже должно быть возможно, но мой мозг увяз, прежде чем я нашел что-нибудь простое.

В любом случае, вот некоторый тестовый код, если вы хотите попробовать. Чтобы привести кнопку в нужное положение, требуется вечность, но, по крайней мере, она работает. Я оставил все видимым во время процесса загрузки, чтобы вы могли видеть, что он делает, на реальной странице было бы лучше держать вещи скрытыми, пока все не будет готово. Также обратите внимание, что выравнивание может быть немного неправильным, потому что я настраиваю ширину по 5 пикселей за раз. Если бы все можно было сделать быстрее, вместо этого было бы легко использовать 1px. Еще лучше, вероятно, будет грубая настройка, чтобы приблизиться, а затем точная настройка, чтобы добиться идеального результата. Очевидно, предстоит много экспериментов, для тех, кто захочет этим заняться.

<!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>

РЕДАКТИРОВАТЬ: немного больше экспериментировал, все еще неудобный обходной путь, но быстрее, чем раньше:

<!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>

ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: это лучшее, что я думаю, что этот метод когда-либо получит; код, безусловно, может быть изменен, но всегда требуется несколько секунд, чтобы пройти пробную ширину, чтобы найти то, что работает. Но теперь это достаточно быстро (около 5 секунд), чтобы его действительно можно было использовать. Кстати, я добавляю каждую новую версию кода, а не заменяю старые, потому что я не проводил большого кросс-браузерного тестирования этого кода, и, возможно, версии с более высокой скоростью не будут работать для кого-то. Поскольку это весь экспериментальный код, я думаю, что лучше иметь разные версии для отката.

<!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>
person Floyd Wilburn    schedule 12.10.2011
comment
Интересный подход, спасибо, что поделились. Это определенно показывает, насколько смехотворна проблема. Надеюсь, кто-нибудь из сотрудников Facebook заглянет и увидит это. - person samvermette; 13.10.2011
comment
Я немного улучшил его, новый код добавлен выше. Но я согласен, это не должно быть необходимо. Все, что потребуется, — это атрибут, который добавит text-align:right к стилю iframe. Что действительно странно, так это то, что, по-видимому, раньше это было возможно, установив для ширины данных значение 0, из-за чего iframe автоматически выбирал подходящую ширину. Это явно больше не работает, что означает, что оно было намеренно удалено?! - person Floyd Wilburn; 18.10.2011

Если вы используете XFBML-версию кнопки «Мне нравится» вместе с Facebook Javascript SDK, вы можете подписаться на событие «xfbml.render», и как только это событие сработает, вы можете установить ширину iframe кнопки «Нравится» на небольшое значение. . (Я использую 50 пикселей.) Затем iframe автоматически настраивает свою ширину по мере необходимости, чтобы отображать кнопку, количество лайков и любые другие элементы в соответствии с вашей конфигурацией.

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

Самым большим препятствием для этого решения является то, что вам понадобится идентификатор приложения Facebook. Вы можете получить идентификатор приложения, создав приложение здесь: https://developers.facebook.com/apps/.

person Pascal    schedule 08.04.2012
comment
+1 Это действительно сработало (к моему удивлению). Единственная проблема, которая остается, заключается в том, что если пользователю нравится, а затем не нравится, коробка не сожмется, чтобы соответствовать состоянию, которому не нравится, но мне этого достаточно, я не собираюсь больше тратить на это энергию. - person Daniel; 18.06.2012

Исправление CSS

.fb-like, 
.fb-like > span,
.fb-like > span iframe {
    max-width:273px;
}
person Tym3k    schedule 25.08.2012
comment
Предоставляя код, решающий проблему, лучше также дать хотя бы краткое объяснение того, как он работает, чтобы читающим людям не пришлось мысленно разбирать его построчно, чтобы понять различия. - person Fluffeh; 28.09.2012

Лично я использую следующие...

#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*/
}

Что я сделал здесь, так это поместил кнопку fb в крайний правый угол, чтобы она выровнялась с моим краем, и только добавленные комментарии (динамические по ширине) будут отображаться за краем. Я могу сохранить хороший дизайн, отображая комментарии, независимо от длины.

person Jacob Thomason    schedule 08.09.2012

Есть несколько ответов на часто задаваемые вопросы, которые стоит прочитать при выборе размера.

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

Хотя с учетом сказанного это все еще довольно загадочно:

Ширина плагина. Выбранный вами макет влияет на минимальную ширину и ширину по умолчанию, которую вы можете использовать. Дополнительные сведения см. в разделе часто задаваемых вопросов ниже.

стандартный

Минимальная ширина: 225 пикселей.

Минимум увеличивается на 40 пикселей, если действие «рекомендуется», и увеличивается на 60 пикселей, если для отправки установлено значение «true».

Ширина по умолчанию: 450 пикселей. Высота: 35 пикселей (без фотографий) или 80 пикселей (с фотографиями).

box_count

Минимальная ширина: 55 пикселей. Ширина по умолчанию: 55 пикселей. Высота: 65 пикселей.

button_count

Минимальная ширина: 90 пикселей. Ширина по умолчанию: 90 пикселей. Высота: 20 пикселей.

кнопка

Минимальная ширина: 47 пикселей. Ширина по умолчанию: 47 пикселей. Высота: 20 пикселей.

person Simon_Weaver    schedule 20.05.2014
comment
Отлично! Это решило мою проблему размещения кнопки FB на странице, которая должна быть отзывчивой и должна работать на мобильном телефоне шириной 300 пикселей. Макет по умолчанию имеет ширину 450 пикселей, независимо от настроек, и вызывает горизонтальную полосу прокрутки для лишнего пространства на 150 пикселей справа от содержимого страницы. Макет button_count не вызывает такой полосы прокрутки. - person Roland; 11.10.2016

Мне пришлось столкнуться с этой же проблемой с плагином add-this и решить ее аналогичным образом:

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

Я добавил это в свой CSS:

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

div.fb-like.fb_iframe_widget{
 width: 100%;
}
person patrick    schedule 11.05.2016