I'm developing a React/MaterialUI component that will be embedded in existing websites.
In order to minimise the work needed on the existing page to embed my component, I'm bundling my component into an app.js and the only change requested to the existing page is something like:
<div id="embedded-component"></div>
<script type="text/javascript" src="https://example.com/app.js"></script>
my component finds the div by ID and then mounts on that element.
Things are mostly working but I'm having issues with CSS conflicts between the CSS files on the original page (which I can't modify) and the elements of my application.
For example the original page uses text input elements with a border/padding/color that I don't want my component to "inherit".
I want my component to display the same way regardless of which page is embedded on.
Is there any strategy/tool to use in this case, so CSS classes on existing page do not affect the elements of my embedded component?
Trying to find a solution to this I've come across the Shadow DOM (e.g. https://medium.com/rate-engineering/winning-the-war-of-css-conflicts-through-the-shadow-dom-de6c797b5cba) but I'm not sure how widely supported this is in different browsers.
Is there any solution to this, that is widely supported by all major browsers?
I cannot use iframes and have full control of my js/css files but no control over the existing page other than the "mounting" div.
Lately, I've noticed something strange, happening only in Chrome (my current version is 58).
It is a little bit difficult to explain, so I made sure to include clear animations besides my text explanation to show what is really happening:
The <h1> text is visible, notice how the computed color is #222, the content is above (I mean, it doesn't look like any z-index fault). But still, the text is not readable unless I resize the page or do some modification using devtools. It can be selected/highlighted though.
The application is built with Angular if that can help in any way, and I'm not using any sort of DOM encapsulation such as Shadow DOM.
I am using a set of shared styles (for example -- colors.scss), which I import in most of my modules.
home.module.ts -> home.component.ts -> home.component.scss
#import "../shared/colors.scss";
One of this shared stylesheets was typography.scss, which had the following (only relevant bits shown):
#font-face {
font-family: "Sawasdee";
src: url("/assets/fonts/sawasdee.ttf") format("truetype");
}
Repetitively importing the font was causing that screen flickering, so all I had to do was to make sure it was only being loaded once (and at the beginning of the app).
So I just moved the font import into the main module scss -> app.component.scss
When I route from one component to another then CSS is not applied for that new component. But when I inspect the element it shows css properties are applied to the element but not rendered. But when I refresh the page or even close the dev tools then that element is displayed on screen immediately without making any changes.
So not sure how to go about resolving this issue.
This issue was related to fonts.
As we are using angular-cli which uses webpack to bundling.
Webpack was unable to bundle fonts properly which was causing it to not render the elements correctly.
Its a known issue in angular-cli
https://github.com/angular/angular-cli/issues/1463
I'm bringing a Twitter feed through to my site using the following code which is described on https://publish.twitter.com/
<a class="twitter-timeline" href="https://twitter.com/ACCOUNT-HERE" data-tweet-limit="3">Tweets by</a>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
The feed is displayed correctly. However it uses CSS which is provided via Twitter.
When I inspect it using Chrome dev tools I can see the following classes around the Tweets:
<p class="timeline-Tweet-text" lang="en" dir="ltr">
So I thought it would be a simple case of targetting this in CSS, e.g.
.timeline-Tweet-text {
}
However, this doesn't apply any styles to the Tweets. Why not?
I have also referred to Twitters guidance on this here https://dev.twitter.com/web/overview/css but that also doesn't work.
The only reason I want to do this is so the font used within the widget matches the font used by the rest of the body text on my website.
Simply adding a style rule to your top-level page won't work, because they are two different and isolated documents as far as the browser is concerned.
However, with the use of kevinburke's Customize Twitter 1.1 project, you should be able to embed CSS into a timeline. It does this by injecting a link to an external CSS file directly into the contents of the document within that frame.
In Kevin's published example, It makes all the text white, which looks a bit broken, but when I took this example and adjusted it to also turn the background red, we can see it's working as intended and you can therefore make any adjustments you like, provided you have a CSS file for it.
Note that this is only possible because Twitter have configured platform.twitter.com so that it can be embedded in frames. For security reasons, many websites will nowadays send a HTTP response header to prevent framing of the content, to avoid people meddling with their contents.
From https://dev.twitter.com/docs/embedded-timelines
Customization Options
Embedded timelines are available in light and dark themes for customization. The light theme is for pages that use a white or light colored background and follows the twitter.com aesthetic, while the dark theme is for pages that use a black or dark color background and looks more like Tweetdeck.
As with your twitter.com profile, you may choose a custom link color for your embedded timelines so that the content matches the links of your website and feels integrated into the color palette of your site.
For sites where the theme and link color do not provide enough customization to make the Tweets feel like they’re a part of the page, we offer a set of additional client side customization features. These settings allow you to control the background color, borders, header, and footer of the timeline, and are detailed in the “Client Side Options” section below
You Can Use CSS * Property for Setting the Fonts for all the Pages...
Example:(this might be useful for you)
#twitterFeed * {
font-family: "Lato" !important;
}
Reference Link for Twitter Widget Style :
https://dev.twitter.com/web/overview/css
https://www.solodev.com/blog/web-design/styling-your-websites-twitter-feed.stml
Unfortunately (Unless it has been changed recently) you can't manipulate CSS inside of an iframe
https://jsfiddle.net/tm94g9n4/5/
.timeline-Tweet-text {color: red;}
I added the color red to the text but as you can see when you inspect it doesn't even appear as overwritten. It's not referenced at all.
I think you'll need to look in to custom libraries for this. I can't recommend any as I've not done this before.
https://stackoverflow.com/a/6495816/1379450
Hope it helps
EDIT
It seems it is possible (Duplicate question)
How to apply CSS to iframe?
I have implemented a simple solution in my project recently, you can customize all kinds of styles to have it fit in seamlessly with your website branding.
jQuery('.twitter-block').delegate('#twitter-widget-0','DOMSubtreeModified propertychange', function() {
//function call to override the base twitter styles
customizeTweetMedia();
});
var customizeTweetMedia = function() {
// overrides font styles and removes the profile picture and media from twitter feed
jQuery('.twitter-block').find('.twitter-timeline').contents().find('.timeline-Tweet-media').css('display', 'none');
jQuery('.twitter-block').find('.twitter-timeline').contents().find('img.Avatar').css('display', 'none');
jQuery('.twitter-block').find('.twitter-timeline').contents().find('span.TweetAuthor-avatar.Identity-avatar').remove();
jQuery('.twitter-block').find('.twitter-timeline').contents().find('.timeline-Tweet-text').css('font-size', '12px');
jQuery('.twitter-block').find('.twitter-timeline').contents().find('.timeline-Tweet-text').css('font-family', "'Proxima Nova', lato, sans-serif");
jQuery('.twitter-block').find('.twitter-timeline').contents().find('span.TweetAuthor-screenName').css('font-size', '12px');
jQuery('.twitter-block').find('.twitter-timeline').contents().find('span.TweetAuthor-screenName').css('font-family', "'Proxima Nova', lato, sans-serif");
// also call the function on dynamic updates in addition to page load
jQuery('.twitter-block').find('.twitter-timeline').contents().find('.timeline-TweetList').bind('DOMSubtreeModified propertychange', function() {
customizeTweetMedia(this);
});
}
Link to my complete example
PROBLEM:
I've created a custom "properties" grid system to use universally on any element. In every project thus far, I've had no problem using it...But when I try to use it in the Polymer Shop App Demo, it doesn't work. Here's my custom property system that I'm importing in: https://github.com/oneezy/steel-properties
In Chrome dev tools network tab, it says that it's loading normally, however when I inspect an element it doesn't show up in the css and has no effect! It's got me scratching my head because it works completely fine w/ Polymer Starter Kit and in other projects...
I've included a short video showing my problem:
https://www.youtube.com/watch?v=tpyYxXTMdkU
Is there something I'm missing or doing wrong???
UPDATE:
By changing shadow to shady in the shop app's index.html file, everything seems to work as expected:
Polymer = {lazyRegister: true, dom: 'shadow'};
becomes...
Polymer = {lazyRegister: true, dom: 'shady'};
But what are the ramifications of this?
Steel-Properties is meant to be used as a "universal" way for initial layout so you can quickly use it on any element. When I include steel-properties into a file, it goes in and calls other files that have specific style properties written out, and you then can write these properties directly into your markup.
EXAMPLE:
HTML Markup:
<body mobile-bg="blue" tablet-bg="green" desktop-bg="yellow"></body>
Output:
The Code:
As you can see, steel-properties is not your typical <custom-element>. It's really just importing in style sheets with [attribute="property"]'s.
So my questions now are:
Should I be doing it this way or am I going about it wrong?
What would be the proper way to write my "steel-properties" so that it can work with both shadow and shady DOM universally?
What are the ramifications of switching shadow to shady DOM in the shop app?
What is the main reason for using shadow DOM instead of shady DOM in the shop app but not the Polymer Starter Kit? (performance?)