新Twitter小部件的iframe CSS覆盖

14

我正在尝试自定义新的Twitter小部件,但在CSS方面遇到了一些问题,似乎无法覆盖他们在这个新小部件上的样式。我已经尝试搜索解决方案,但没有找到与之匹配的解决方法。

这是我的页面,右侧导航栏中有该小部件和用于“.timeline”类的调整后的CSS:

.timeline {
margin-bottom:0;
border:0 !important;
border-radius:0 !important;
-webkit-border-radius:0;
-moz-border-radius:0;
}

HTML:

<div class="bg">
<h3 class="twitter">Twitter News</h3>
<div id="twitter">
<a class="twitter-timeline" href="https://twitter.com/" data-widget-id="268336500536647680">Tweets by </a>
<script>!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>
</div></div>

我已经开始使用!important声明,并尝试使用主要的#twitter id进行覆盖,但都不起作用。

非常感谢任何想法。

显然,我需要以某种方式编辑iframe,但不确定如何操作 - 如果有人对如何在我的代码中实现这一点(而不是通过教程)有更清晰的想法,那将非常棒。我还需要更改iframe的宽度..

8个回答

27

我用JavaScript(在我的应用中使用jQuery!)实现了这一点。您必须在iframe加载后应用样式(我没有找到有效的“已加载”事件,因此我使用轮询策略)。

// Customize twitter feed
var hideTwitterAttempts = 0;
function hideTwitterBoxElements() {
    setTimeout( function() {
        if ( $('[id*=twitter]').length ) {
        $('[id*=twitter]').each( function(){
            if ( $(this).width() == 220 ) {
                $(this).width( 198 ); //override min-width of 220px
            }
            var ibody = $(this).contents().find( 'body' );
            ibody.width( $(this).width() + 20 ); //remove scrollbar by adding width

            if ( ibody.find( '.timeline .stream .h-feed li.tweet' ).length ) {
            ibody.find( '.timeline' ).css( 'border', 0 );
            ibody.find( '.timeline .stream' ).css( 'overflow-x', 'hidden' );
            ibody.find( '.timeline .stream' ).css( 'overflow-y', 'scroll' );
            ibody.find( '.timeline-header').hide();
            ibody.find( '.timeline-footer').hide();
            }
            else {
                $(this).hide();
            }
        });
        }
        hideTwitterAttempts++;
        if ( hideTwitterAttempts < 3 ) {
            hideTwitterBoxElements();
        }
    }, 1500);
}

// somewhere in your code after html page load
hideTwitterBoxElements();

+1 干得好;-) 不确定这在所有情况下都能起作用,但已经成功在 Firefox 测试案例中隐藏了头像。 - virtualeyes
5
你可以使用这里定义的函数https://dev59.com/xW035IYBdhLWcg3wQtun#13709125 来执行以下操作:$("iframe#twitter-widget-0").waitUntilExists(function(){ // 格式化 }); - Nicolas
如果您不想使用setTimeout,可以使用:https://gist.github.com/buu700/4200601 - Francisco Corrales Morales

7

以下内容供对jQuery不感兴趣的人参考。

更新:我们有了更好的解决方案,不再依赖轮询,因此不会出现偶尔的无样式布局问题:

twttr.events.bind('rendered',function(){
  [].slice.call(document.querySelectorAll('iframe.twitter-timeline')).forEach(function(e,i,a){
    var fE = e.contentDocument.getElementsByClassName('timeline-footer');
    if(fE.length){
      fE[0].style.backgroundColor='transparent';
    }
  });
});

旧版本:

// Customize twitter feed                                                                              
var hideTwitterAttempts = 0;                                                                           
function hideTwitterBoxElements() {                                                                    
    setTimeout( function() {                                                                           
        var list = document.getElementsByTagName('iframe');                                            
        if (list.length ) {                                                                            
            Array.prototype.forEach.call(                                                              
                list,                                                                                  
                function(element){                                                                     
                    var footerE = element.contentDocument.getElementsByClassName('timeline-footer')[0];
                    footerE.style.backgroundColor="transparent";                                       
                });                                                                                    
        }                                                                                              
        hideTwitterAttempts++;                                                                         
        if ( hideTwitterAttempts < 3 ) {                                                               
            hideTwitterBoxElements();                                                                  
        }                                                                                              
    }, 1500);                                                                                          
}                                                                                                      
hideTwitterBoxElements();                                                                              

我在JS方面很业余...你能解释一下这段代码吗?特别是hideTwitterAttempt变量? - MonteCristo
哦,hideTwitterAttempts只是限制了我尝试隐藏背景的次数(3次)。这是一个简单的计数器变量,我不想让页面挂起(等待抛出太多递归错误),如果发生了什么问题(例如 Twitter 更改其小部件),因此我限制了脚本的潜在运行时间。Array.prototype.forEach.call 语法是因为 document.getElementsByTagName 返回一个节点列表而不是数组,所以我无法直接调用 foreach - Camden Narzt
嗨,我尝试了您答案的修改版本,在IE9上。这是我的代码:function(element){ var foo= element.contentDocument.getElementsByClassName('tweet-actions')[0]; foo.style.display="none"; }); 但是在IE 8或9中无法正常工作。但是在Firefox,Chrome和Safari中可以。您能告诉我哪里出错了吗? - bongman1612
我不是IE专家,所以我的第一反应是这可能是由于IE的JS解释器中的某些非标准行为或者他们的安全策略导致的。你能否打开开发者工具,重新加载页面并告诉我有哪些错误被报告了?这可能很难在评论中进行调试,因此您可能需要打开一个问题并在回复中链接到它。 - Camden Narzt
Camden,我有一个问题 - 我尝试使用 .header 作为目标来消除推文作者信息(它们都来自同一用户),但似乎只对第一个有效。有没有办法同时针对所有的信息进行操作? - Octavian
我在代码中只特意更改结果的第一个元素(请参见零索引:[0]),因此要想更改它们所有,请用forEach()调用替换索引,并将您的逻辑放在闭包中。 - Camden Narzt

6

我从@Sebastiaan Ordelman那里修改了这段代码,并加入了一些注释(参考旧API的值)。这是我在短时间内尝试匹配旧API的努力。将此代码放置在您从新版Twitter小部件中复制并粘贴代码后。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
var hideTwitterAttempts = 0;
function hideTwitterBoxElements() {
    setTimeout( function() {
        if ( $('[id*=twitter]').length ) {
        $('[id*=twitter]').each( function(){
            var ibody = $(this).contents().find( 'body' );

            if ( ibody.find( '.timeline .stream .h-feed li.tweet' ).length ) {
            ibody.find( '.customisable-border' ).css( 'border', 0 );
            ibody.find( '.timeline' ).css( 'background-color', '#004A7B' ); //theme: shell: background:
            ibody.find( 'ol.h-feed' ).css( 'background-color', '#0575A1' ); //theme: tweets: background:
            ibody.find( 'ol.h-feed' ).css( 'border-radius', '5px 5px 5px 5px' );
            ibody.find( 'li.tweet' ).css( 'border-bottom', '1px dotted #FFFFFF' ); //theme: tweets: color:
            ibody.find( 'li.tweet' ).css( 'color', '#FFFFFF' ); //theme: tweets: color:
            ibody.find( '.customisable:link' ).css( 'color', '#07E0EB' ); //theme: tweets: links:
            ibody.find( '.footer' ).css( 'visibility', 'hidden' ); //hide reply, retweet, favorite images
            ibody.find( '.footer' ).css( 'min-height', 0 ); //hide reply, retweet, favorite images
            ibody.find( '.footer' ).css( 'height', 0 ); //hide reply, retweet, favorite images
            ibody.find( '.avatar' ).css( 'height', 0 ); //hide avatar
            ibody.find( '.avatar' ).css( 'width', 0 ); //hide avatar
            ibody.find( '.p-nickname' ).css( 'font-size', 0 ); //hide @name of tweet
            ibody.find( '.p-nickname' ).css( 'visibility', 'hidden' ); //hide @name of tweet
            ibody.find( '.e-entry-content' ).css( 'margin', '-25px 0px 0px 0px' ); //move tweet up (over @name of tweet)
            ibody.find( '.dt-updated' ).css( 'color', '#07E0EB' ); //theme: tweets: links:
            ibody.find( '.full-name' ).css( 'margin', '0px 0px 0px -35px' ); //move name of tweet to left (over avatar)
            ibody.find( 'h1.summary' ).replaceWith( '<h1 class="summary"><a class="customisable-highlight" title="Tweets from fundSchedule" href="https://twitter.com/fundschedule" style="color: #FFFFFF;">fundSchedule</a></h1>' ); //replace Tweets text at top
            ibody.find( '.p-name' ).css( 'color', '#07E0EB' ); //theme: tweets: links:
            }
            else {
                $(this).hide();
            }
        });
        }
        hideTwitterAttempts++;
        if ( hideTwitterAttempts < 3 ) {
            hideTwitterBoxElements();
        }
    }, 1500);
}

// somewhere in your code after html page load
hideTwitterBoxElements();
</script>

变化的形象:http://img837.imageshack.us/img837/1139/btjc.png

(Note:此处为一段HTML代码,无法直接翻译)

5

虽然这并没有直接回答问题中与CSS相关的部分,但我认为为了完整性值得注意的是,一些你想要的功能(例如隐藏边框/标题)可以通过widget中传递的data-属性来实现:

<a class="twitter-timeline" href="https://twitter.com/twitterapi" 
    data-widget-id="YOUR-WIDGET-ID-HERE" 
    data-theme="dark"
    data-chrome="noheader nofooter noborders noscrollbar transparent"
    data-link-color="#cc0000"
    width="200"
    height="300"
    >Tweets by @twitterapi</a>
https://dev.twitter.com/docs/embedded-timelines#customization 是关于嵌入式时间轴自定义的文档。在可能的情况下,最小化javascript交互可能会带来性能上的好处。

3
他们创建了一个iframe,因此它是另一个文档。 你不能样式化另一个文档中的元素,除非Twitter提供了在其iframe中嵌入自己样式表的钩子。 Twitter只允许样式化小部件链接颜色(widget link color)和选择浅色/深色主题。

或者,您可以使用Twitter API创建自己的小部件,然后您可以按照任何想要的方式进行样式设置。


1

我不知道当时提问时是否可能,但现在是可以的,请查看文档

<a class="twitter-timeline" data-chrome="nofooter" ....">Tweets</a>

1
抱歉..在我发布之前我忽略了你的答案 - 很好。 - ptim

1
可能更好的方式是使用Twitter的事件结构。
根据 https://dev.twitter.com/web/javascript/loading
<script>window.twttr = (function (d, s, id) {
  var t, js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src= "https://platform.twitter.com/widgets.js";
  fjs.parentNode.insertBefore(js, fjs);
  return window.twttr || (t = { _e: [], ready: function (f) { t._e.push(f) } });
}(document, "script", "twitter-wjs"));</script>

根据https://dev.twitter.com/web/javascript/events,您的事件和挂钩将类似于以下内容(请注意,此示例使用jquery,您也可以选择仅使用javascript)

twttr.ready( function(twttr){
    twttr.events.bind("rendered", function(tw_event){
    var tw_iframe = ev.target;

    //the following is custom jquery code to do various 
    //css overrides based on selectors
    var twitterbody = $(tw_iframe).contents().find( 'body' );
       twitterbody.find(".avatar").hide();
       twitterbody.find("li.tweet").css({padding: "2px"});
    });
});

0

这就是关键,你无法更改外部iframe的CSS。但是,你可以使用Twitter API创建自己的插件,然后对CSS进行任何想要的更改... - SimonW
不过它并不是一个不同的域,Twitter使用JavaScript创建和填充iframe,因此同源策略不适用。 - Camden Narzt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接