I found the first solution to activated a scroll, but it didn't work for me. ul block does not scroll down when switching elements using the down arrow on the keyboard.
my version react-autosuggest is "^10.1.0"
.react-autosuggest__suggestions-list {
margin: 0;
padding: 0;
max-height: 200px;
overflow-y: auto;
}
https://codesandbox.io/s/react-autosuggest-forked-4519do?file=/src/styles.css
I solved this problem by replacing the .react-autosuggest__suggestions-list class to #react-autowhatever-1
Related
I wrote a Google Chrome extension, which popups a dialog with an autocomplete field and it's own style, but there are some sites where my CSS gets totally broken, which doesn't look very nice.
I know about isolating styles with iFrames, but in Google Chrome extension there is no way to isolate my HTML and CSS in this way. Another method is to wrap all my stuff into a separated div with it's own id and relative styles for that id, and I do so, but it seems that it doesn't work on some sites with "hard" tags style overloading or "!important" directives in the CSS code.
So, I want to know is there any way to really isolate my styles in z convenient way or it's my bad carma to overload every little CSS property to fix one or another style issue for each site?
By the way: I set up my manifest to load all the things at the "document_end", but I see it's not being applied to the stylesheets which is every time loaded whenever the DOM is ready.
At the time of asking the question, your only option was to either use iframes, or stylesheets with a very high specificity and explicitly set all properties that might affect styles. The last method is very cumbersome, because there will always be some property that is overlooked by you. Consequently, the only usable method for isolating stylesheets was to use iframes.
The solution to this problem -isolation of styles without iframes- is Shadow DOM (since Chrome 25). You can find a tutorial at HTML5 Rocks. For a real-world Chrome extension that uses Shadow DOM to isolate styles, see Display #Anchors (source code here).
As I've recently gone through the gauntlet of this issue, I want to share some information I think is valuable.
First, Rob W's answer is correct. Shadow DOM is the correct solution to this problem. However, in my case not only did I need CSS isolation, I also needed JavaScript events. For example, what happens if the user clicks a button that lives within the isolated HTML? This gets really ugly with just Shadow DOM, but we have another Web Components technology, Custom Elements, to the rescue. Except that as of this writing there is a bug in chrome that prevents custom element in chrome extensions. See my questions here and here and the bug here.
So where does that leave us? I believe the best solution today is IFrames, which is what I went with. The article shahalpk linked is great but it only describes part of the process. Here's how I did it:
First, create an html file and js file for your isolated widget. Everything inside these files will run in an isolated environment in an iframe. Be sure to source your js file from the html file.
//iframe.js
var button = document.querySelector('.my-button');
button.addEventListener('click', function() {
// do useful things
});
//iframe.html
<style>
/* css */
</style>
<button class='my-button'>Hi there</button>
<script src='iframe.js'></script>
Next, inside your content script create an iframe element in javascript. You need to do it in javascript because you have to use chrome.extension.getURL in order to grab your iframe html file:
var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL("iframe.html");
document.body.appendChild(iframe);
And that's it.
One thing to keep in mind: If you need to communicated between the iframe and the rest of the content script, you need to chrome.runtime.sendMessage() to the background page, and then chrome.tabs.sendMessage from the background page back to the tab. They can't communicate directly.
EDIT: I wrote a blog post detailing everything I learned through my process, including a complete example chrome extension and lots of links to different information:
https://apitman.com/3/#chrome-extension-content-script-stylesheet-isolation
In case my blog goes down, here's the sources to the original post:
Blog post
Example source
Either use all
.some-selector {
all: initial;
}
.some-selector * {
all: unset;
}
or use Shadow DOM
Library
function Widget(nodeName, appendTo){
this.outer = document.createElement(nodeName || 'DIV');
this.outer.className = 'extension-widget-' + chrome.runtime.id;
this.inner = this.outer.createShadowRoot();
(appendTo || document.body).appendChild(this.outer);
}
Widget.prototype.show = function(){
this.outer.style.display = 'block';
return this;
};
Widget.prototype.hide = function(){
this.outer.style.display = 'none';
return this;
};
Usage
var myWidget = new Widget();
myWidget.inner.innerHTML = '<h1>myWidget</h1>';
You can access the widget contents via myWidget.inner and the outer via myWidget.outer.
Styles
/*
* Reset Widget Wrapper Element
*/
.extension-widget-__MSG_##extension_id__ {
background: none;
border: none;
bottom: auto;
box-shadow: none;
color: black;
cursor: auto;
display: inline;
float: none;
font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: inherit;
font-style: normal;
font-variant: normal;
font-weight: normal;
height: auto;
left: auto;
letter-spacing: 0;
line-height: 100%;
margin: 0;
max-height: none;
max-width: none;
min-height: 0;
min-width: 0;
opacity: 1;
padding: 0;
position: static;
right: auto;
text-align: left;
text-decoration: none;
text-indent: 0;
text-shadow: none;
text-transform: none;
top: auto;
vertical-align: baseline;
white-space: normal;
width: auto;
z-index: 2147483648;
}
/*
* Add your own styles here
* but always prefix them with:
*
* .extension-widget-__MSG_##extension_id__
*
*/
.extension-widget-__MSG_##extension_id__{
position: fixed;
top: 100px;
margin: 0 auto;
left: 0;
right: 0;
width: 500px;
}
.extension-widget-__MSG_##extension_id__::shadow h1 {
display: block;
margin: 0 auto;
padding: 20px;
background-color: yellow;
border: 10px solid green;
font-size: 20px;
text-align: center;
}
I recently created Boundary, a CSS+JS library to solve problems just like this. Boundary creates elements that are completely separate from the existing webpage's CSS.
Take creating a dialog for example. After installing Boundary, you can do this in your content script
var dialog = Boundary.createBox("yourDialogID", "yourDialogClassName");
Boundary.loadBoxCSS("#yourDialogID", "style-for-elems-in-dialog.css");
Boundary.appendToBox(
"#yourDialogID",
"<button id='submit_button'>submit</button>"
);
Boundary.find("#submit_button").click(function() {
// some js after button is clicked.
});
Elements within #yourDialogID will not be affected by the existing webpage. And find() function returns a regular jQuery DOM element so you can do whatever you want with it.
Hope this helps. Please let me know if you have any question.
https://github.com/liviavinci/Boundary
Use iframes. It's a workaround, but works fine.
Maxime has written an article on it.
click one of the card
the card expands and pops up
tried to scroll but only scrolling the background page while I wanted to scroll down to view more text
I already tried overflow:hidden which doesn't scroll ( and the scroll bar is ugly)
How can I solve this ? thank you very much !
https://codesandbox.io/s/framer-motion-animatesharedlayout-app-store-demo-i1kct?from-embed
It looks like a few things are preventing the scroll:
height: auto sizes the container to fit the content.
overflow: hidden instead of scroll.
pointer-events: none prevents the element from getting the scroll events.
Changing this block in styles.css:
.open .card-content {
height: auto;
max-width: 700px;
overflow: hidden;
pointer-events: none;
}
to this:
.open .card-content {
max-width: 700px;
overflow-y: scroll;
}
seems to work.
I make a responsive web page where at max width of 768px (via media query) the div inside the main container suppose to change to inline-block so that the page would scroll horizontally to the div's id when user click on link. The page is set up with overflow: hidden, so it navigate using id/anchor alone.
The problem is, when I did a preview in mobile, the container just spread out and I can totally swipe the page. Even the menu button that suppose to be in the center of the view port went to the center of the container. And leaving a huge white space below it. It did good however in desktop browser. So I presume it has everything to do with the nowrap function.
It worked in Firefox both mobile and desktop. It worked in I.E desktop. It did not worked in Chrome mobile but seems to be working in desktop. And failed in Safari mobile, haven't tested yet in desktop.
I tried to remove white-space: nowrap function only to find out the div did not stacks inline-block like it suppose to. I tried specified container's width and min-width with no luck. I tried float: left, position values and a bunch of things i don't recall them all. Nothing's change.
HTML
<div id="container">
<div id="company" class="company">
<iframe src="main.html">
</iframe>
</div>
<div id="content" class="content">
<iframe src="content.html">
</iframe>
</div>
<div id="system" class="system">
<iframe src="system.html">
</iframe>
</div>
</div>
css
body{
overflow: hidden;
}
#container {
height: 100vh !important;
min-height: 100vh !important;
}
#container .company, #container .content, #container .system {
display: block;
height: 100vh !important;
min-height: 100vh !important;
}
#media screen and (max-width:768px) {
#container {
display: block;
white-space: nowrap;
}
#container .company, #container .content, #container .system {
display: inline-block;
}
}
iframe {
width: 100vw !important;
min-width: 100vw !important;
height: 100vh !important;
min-height: 100vh !important;
border: none;
}
What I expected (Chrome desktop)
https://kamalmasrun.files.wordpress.com/2019/01/desktop.jpg
But only comes to this in mobile
https://kamalmasrun.files.wordpress.com/2019/01/screenshot_20190122-120510.png
Your help is much appreciated and I first address a thank you to all for the help =).
Basically, you have a few problems here:
Setting overflow: hidden won't prevent browser on mobile from scrolling (on Firefox it might, but on Chrome or iOS Safari it will not). Blocking scrolling is a hard thing to do on mobile to be honest, and it always is a little bit hacky, so I would not go that way.
To achieve scrolling (or jumping) using links with #content etc, body has to be expanded and browser has to see where this element is. Expanding body will result in ability for user to scroll left/right, which is hard to block as I mentioned before. You have to scroll #container to show new element. You can do this using javascript.
Also, don't forget to add overflow: hidden to #container (this will work on mobile).
If something is still unclear, feel free to ask in comments below this answer :)
The idea of algorithm to achieve your goal:
Listen to hashchange event
Read current hash from window.location
Find element with given hash using document.querySelector
Read element's position inside container
Set scrollLeft property of container to be equal element's position
Some useful links to get you started:
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onhashchange
https://developer.mozilla.org/en-US/docs/Web/API/Window/location
https://developer.mozilla.org/pl/docs/Web/API/Document/querySelector
https://developer.mozilla.org/pl/docs/Web/API/Element/getBoundingClientRect
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
And updated CSS:
body {
overflow: hidden;
margin: 0;
}
#button {
position: fixed;
vertical-align: center;
}
#button .btn1,
.btn2,
.btn3 {
padding: 10px;
display: inline-block;
}
#container .company,
.content,
.system {
display: block;
height: 100vh;
min-height: 100vh;
width: 100vw;
}
#media screen and (max-width:768px) {
#container {
display: flex;
flex-flow: row nowrap;
}
#container .company,
.content,
.system {
display: block;
}
}
iframe {
border: none;
height: 100vh;
min-height: 100vh;
width: 100vw;
}
It's possible that setting min/max width to #container will do the trick.
#container {
min-width: 100vw;
max-width: 100vw;
}
Also, I'd suggest using flex here, as it would suit well and is more modern.
A client is requiring us to add a vertical line in between our angular material tabs. While this appears to be frowned upon, we cannot figure out how to accomplish this.
Here is an example:
Angular Material tabs
We've tried the angular md-divider but this only appears to work for vertical lists that need a horizontal line. Any help is appreciated.
It would be a mistake to add markup just for styling, in my opinion. I'd either use borders or pseudo-elements.
.md-tab {
border-right: 1px solid red;
}
Demo 1
.md-tab:after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 3px;
background: green;
}
Demo 2
To hide the last tab's border you could add a class using Angular's $last and target that (or add it manually if you're not using ng-repeat).
ng-class="{'last-tab-class': $last}"
.md-tab.last-tab-class {
border-right: none;
}
add custom style to md-divider
<md-divider class="vertical-divider"></md-divider>
.vertical-divider {
border-top-width: 0;
border-right-width: 1px;
border-right-style: solid;
height: 100%;
}
I suspect this is a case of not really understanding CSS3 animations, but in general, I've found Angular animation very frustrating to learn.
So to start, I have a plunker for this: http://plnkr.co/edit/VSIxhDy1qaVuF0j0pxjT?p=preview
As I'm required to show code to get a plunker link going, here's the CSS in the test situation:
#wrapper {
position: relative;
overflow: hidden;
}
#wrapper, form, #wrapper > div {
height: 400px;
width: 400px;
}
#wrapper > * {
transition: 10s linear all;
}
form {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
form.ng-hide-add-active {
top: -100%;
}
#wrapper > div {
position: absolute;
left: 0;
top: 0;
background: #66F;
}
#wrapper.ng-hide.ng-hide-remove-active {
top: 100%;
}
I have a situation where I want to make a form, and if it successfully submits, I want the form to slide up with the success message sliding up under it. The problem is that while I can get the form to slide away, the under div just appears. In fact, it works better on plunker than on my code, where it starts up shown, goes away via animation, then just reappears when the form is submitted. No idea why that's the case, but in general, Angular animations are frustrating me. I tried looking up examples, and many mention using ng-animate="'name'" to create custom classes, but that doesn't seem to work for me. Likewise, the documentation mentions an ng-hide-remove class, but I never see that getting applied.
Is there any advantage to using CSS3 transitions over creating custom animations with the animate module, and just using jQuery to do it? I understand keyframes may be the biggest advantage? This is just making it really hard to do stuff that seems relatively easy in jQuery working...
The examples using ng-animate="'name'" is for versions earlier than Angular 1.2.
For these kind of animations, vision two states for each involved element.
Visible
Hidden
You have a wrapper. Inside the wrapper you have two elements involved in the animation - a form and a div with a message. Now set up your HTML and CSS with the visible state in mind. When visible, both the form and the div should be visible inside the container.
Here is an example based on yours (changed it some for clarity):
#wrapper {
position: absolute;
height: 200px;
width: 200px;
top: 100px;
left: 100px;
border: 1px solid silver;
}
#form {
position: absolute;
top: 0;
height: 100%;
width: 100%;
background-color: #DDFEFF;
transition: all 1s ease-in-out;
}
#submitted {
position: absolute;
top: 0;
height: 100%;
width: 100%;
background-color: gold;
transition: all 1s ease-in-out;
}
Both the form and the div are as large as the wrapper and aligned to the wrappers top, which means in this state they will overlap. This is not a problem however, since they shouldn't be visible at the same time.
Now define their hidden states.
For example, the form should when hidden be located above the wrapper:
#form.ng-hide {
top: -100%;
}
And the div should when hidden be located below the wrapper:
#submitted.ng-hide {
top: 100%;
}
That should be enough but minor tweaks might be needed depending on what AngularJS version you are using.
Demo: http://plnkr.co/edit/FDJFHSaLXdoCK7oyVi7b?p=preview