So far I haven't found a solid way to create a sticky header on AMP pages. I know there are CSS workaround/hacks, but nothing I can use in a production environment. A simple "position:fixed;" unfortunately won't work in my case.
Out of all the components, I thought there would be one that toggles a body class on scroll, but I haven't found anything yet. Also don't think "amp-position-observer" will be of any use.
Am I missing something? Ideally I'd like to be able to toggle an element's class name after a scroll of X amount of pixels. Is this possible in AMP?
Toggling an element's classname after a scroll of X amount of pixels is currently not supported as amp-position-observer does not allow changing amp-state.
You can combine amp-position-observer to change parts of the header using amp-animation. However, it's application is limited as the supported CSS properties are limited. Nevertheless, with a little bit of creativity this approach can be quite flexible. One possible pattern is to duplicate elements in your header which are then shown/hidden based on your scrolling position.
Here is a sample highlighting the header based on the currently focused section.
I built a working solution of a sticky header within an amp-list. The pitfall is that amp elements add display: block and position: absolute on many elements.
To use position: sticky you need to use display: inline and position: relative on all subelements on your header. Make sure these are actually applied and not overwritten, use id to get a higher specificity over the amp css classes.
Here's an example using an amp list
css:
All divs need display: inline
The amp-list gets an id (not class) to apply css to itself and the generated child div
Divs can be nested as long as they use display: inline
.sticky {
position: sticky;
z-index: 1;
display: inline-block;
box-sizing: border-box;
width: 100%;
background-color:white;
top: 40px;
}
.inline {
display: inline;
}
#list-wrapper, #list-wrapper>div {
display: inline;
position: relative;
}
<div>
<amp-list [src]="..." items="." single-item layout="flex-item" id="list-wrapper">
<template type="amp-mustache">
<div class="inline">
<span class="sticky">
<span>Sticky header</span>
</span>
</div>
</template>
</amp-list>
<div>Your content</div>
<div>
Related
I am wondering if there is an easier way to target the following css class, because it could cause a little bit of bloat:
I have different single pages, where I want to disable a sticky header effect, because an other element is used to be fixed on that pages. Up to now I select those class by using:
.page-id-xx .header-is-sticky .header {
position: static;
}
If I want to disable the sticky header on 20 pages I am ending up to use the selectors class above 20 times, but only the page-id-xx will change. It'd look like this:
.page-id-1 .header-is-sticky .header,
.page-id-2 .header-is-sticky .header,
.page-id-3 .header-is-sticky .header,
and so on ...
I am wondering, if there is a more intelligent way to target the .header class, maybe with the help of some combiselectors? Or is there a quick javascript snippets? Maybe an if loop by checking for the ID of the element (#subnav), which should be sticky alternativly to the header on that pages?
Thanks in advance :)
Possibly Unnecessary Specificity?
Do you absolutely need the parent selector (i.e. page-id-n), if not, then obviously the following would be quite a bit more elegant :
.header-is-sticky .header {
position: static;
}
Taking Advantage of CSS Selectors
CSS provides a series of attribute selectors that can be used to target certain elements depending on various constraints for their attributes. The starts-with and contains selectors should work for your needs here.
/* This will match any element that has a class attribute that starts with "page-id" */
[class^="page-id"] .header-is-sticky .header {
position: static;
}
/* This will match any element that has a class attribute that contains "page-id" */
[class*="page-id"] .header-is-sticky .header {
position: static;
}
I have a <core-drawer-panel> and inside it is a <core-pages> element inside <core-header-panel main>.
<core-pages> contains a set of custom elements that I have defined and only one of those elements are shown at any point of time. However the problem is, there are elements that take only part of the screen but still scroll vertically. The amount of scrolling is equal to the tallest element within <core-pages>.
The expected behavior is that the element should scroll only if it exceeds it's view port. How can I achieve this behavior?
demo-students.html (Stripped down version, to make it more readable)
<polymer-element name="students-dashboard">
<template>
<style>
…
</style>
<core-drawer-panel…>
<core-header-panel drawer mode="seamed">
…
</core-header-panel>
<core-header-panel main mode="seamed">
<core-toolbar …>
<span flex>Students</span>
</core-toolbar>
<div class="content">
<core-pages selected={{getModule(route)}} valueattr="name">
<!--
This needs to scroll and it does
-->
<students-grid name="students"></students-grid>
<!--
The content of this element is short,
but still scrolls to the same extent as the
<students-grid> element
-->
<student-editor name="student_editor"></students-editor>
</core-pages>
</div>
<core-header-panel>
</core-drawer-panel>
</template>
<script>
…
</script>
</polymer-element>
I don't know if it's the same issue I had: when using <core-pages> it was scrolling beyond the content of the smaller tabs. Each pages had the same size as the biggest page.
Nothing worked except replacing <core-pages> with <animated-core-pages> which made the problem magically disappear.
I had a similar problem with <core-scaffold> from the starter project which was different from the version downloaded by bowser (the same day). A bug disappeared when using the latter.
Tldr: Maybe the starter project is not up-to-date.
PS: this fixed the pages size problem not the fact that the scroll position is keeped across pages.
I've been having a similar struggle but with <core-animated-pages> inside a <core-header-panel> inside a <core-drawer-panel>.
I ended up getting the internal page element to fit and scroll itself by doing the following.
On the main page's css:
core-drawer-panel, core-header-panel {
height: 100%;
}
core-animated-pages { << core-pages for your example
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
flex: 1;
box-sizing: border-box;
}
On the polymer element's css:
:host {
display: block;
flex: 1;
box-sizing: border-box;
overflow-y: auto;
}
Give it a go and let us know how it works.
I want to embed zumi.pl map on my website. Their map is loaded via js to div with specific id and is dependent on external css. However my css for formating div inside div#content interferes with embedded map screwing it all up. I tried to enclose it in another div with contextual css reset but it's still displays wrong. Only way to make it display (almost) properly is to uncheck all my css rules for that div in firefox inspector but I can't figure it out how to achieve the same effect on page.
for clarity this is sample copy&paste code from their generator:
<div id="zumiMap" class="zumi_creator" style="width:300px; height:300px;"></div>
<script src="http://api.zumi.pl/maps/api" type="text/javascript" ></script><script type="text/javascript">(function(){var marker,map=new zumi.maps.Map("zumiMap", {"apiKey": "E48EF8E55A0B3BEAE0434628AE0A1EEA"});map.afterLoad(function() {document.getElementById("zumiMap").className += " zumi_creator";map.addMarker({lat: 52.214679,lng: 21.021101},{letter: "A", type: "main"});map.setCenter({lng: 21.021101,lat: 52.214679}, 7);});})();</script>
and here is my css that's to blame:
#content div {
display: inline;
float: left;
margin: 0px 0.833333%;
padding-left: 10px;
}
How to isolate html fragment so it behaves as there was no previous css rules present?
But without using Iframe.
Did you try this? #content #zumiMap div will have higher specificity than your #content div selector, so you can reset all the problem styles.
#content #zumiMap div {
display: block;
float: none;
margin: 0;
padding-left: 0;
}
This question already has answers here:
How to reset/remove CSS styles for a specific element or selector only
(17 answers)
Closed last month.
I know this question was asked before, but before marking it as a duplicate, I want to tell you that my situation is a little different from what I found on the internet.
I'm building and embedded script that people can put it on their sites. This script creates a div with a certain width/height and some information in it.
My problem is that some websites declare styles for div that are inherited by my div as well.
for example:
div{
background-color:red;
}
so if I don't set any background color to my div, it will show red even if I don't want that.
The only solutions I come along is to overwrite as many css proprieties, this way my div will show exactly as I want.
The problem with this solution is that there are too many css proprieties to overwrite and I want my script to be as light as it can be.
So my question is if you know another solution to my problem.
It can be in css/javascript /jQuery.
Thanks
"Resetting" styles for a specific element isn't possible, you'll have to overwrite all styles you don't want/need. If you do this with CSS directly or using JQuery to apply the styles (depends on what's easier for you, but I wouldn't recommend using JavaScript/JQuery for this, as it's completely unnecessary).
If your div is some kind of "widget" that can be included into other sites, you could try to wrap it into an iframe. This will "reset" the styles, because its content is another document, but maybe this affects how your widget works (or maybe breaks it completely) so this might not be possible in your case.
Only set the relevant / important CSS properties.
Example (only change the attributes which may cause your div to look completely different):
background: #FFF;
border: none;
color: #000;
display: block;
font: initial;
height: auto;
letter-spacing: normal;
line-height: normal;
margin: 0;
padding: 0;
text-transform: none;
visibility: visible;
width: auto;
word-spacing: normal;
z-index: auto;
Choose a very specific selector, such as div#donttouchme, <div id="donttouchme"></div>. Additionally, you can add `!important before every semicolon in the declaration. Your customers are deliberately trying to mess up your lay-out when this option fails.
You could try overwriting the CSS and use auto
I don't think this will work with color specifically, but I ran into an issue where i had a parent property such as
.parent {
left: 0px;
}
and then I was able to just define my child with something like
.child {
left: auto;
}
and it effectively "reset" the property.
Technically what you are looking for is the unset value in combination with the shorthand property all:
The unset CSS keyword resets a property to its inherited value if it inherits from its parent, and to its initial value if not. In other words, it behaves like the inherit keyword in the first case, and like the initial keyword in the second case. It can be applied to any CSS property, including the CSS shorthand all.
.customClass {
/* specific attribute */
color: unset;
}
.otherClass{
/* unset all attributes */
all: unset;
/* then set own attributes */
color: red;
}
You can use the initial value as well, this will default to the initial browser value.
.otherClass{
/* unset all attributes */
all: initial;
/* then set own attributes */
color: red;
}
As an alternative:
If possible it is probably good practice to encapsulate the class or id in a kind of namespace:
.namespace .customClass{
color: red;
}
<div class="namespace">
<div class="customClass"></div>
</div>
because of the specificity of the selector this will only influence your own classes
It is easier to accomplish this in "preprocessor scripting languages" like SASS with nesting capabilities:
.namespace{
.customClass{
color: red
}
}
Try this: Create a plain div without any style or content outside of the red div. Now you can use a loop over all styles of the plain div and assign then to your inner div to reset all styles.
Of course this doesn't work if someone assigns styles to all divs (i.e. without using a class. CSS would be div { ... }).
The usual solution for problems like this is to give your div a distinct class. That way, web designers of the sites can adjust the styling of your div to fit into the rest of the design.
As long as they are attributes like classes and ids you can remove them by javascript/jQuery class modifiers.
document.getElementById("MyElement").className = "";
There is no way to remove specific tag CSS other than overriding them (or using another element).
you may use this below option.
<style>
div:not(.no_common_style){
background-color:red;
}
</style>
now , if their any place where you do not want to apply default style you can use 'no_common_style' class as class.
ex:
<div class="no_common_style">
It will not display in red
</div>
From what I understand you want to use a div that inherits from no class but yours. As mentioned in the previous reply you cannot completely reset a div inheritance. However, what worked for me with that issue was to use another element - one that is not frequent and certainly not used in the current html page. A good example, is to use instead of then customize it to look just like your ideal would.
area { background-color : red; }
One simple approach would be to use the !important modifier in css, but this can be overridden in the same way from users.
Maybe a solution can be achieved with jquery by traversing the entire DOM to find your (re)defined classes and removing / forcing css styles.
I need to override the defined :last-child style defined in my stylesheet using jQuery.
I'm aiming for minimal markup using a combination of css and jQuery where the structure around "container-content" is appended to the div on document-ready.
<div id="title-some-impact"><!--Vertical container title--></div>
<div class="container-content-wrapper">
<div></div>
<div class="container-content"><!--Actual container content-->
<div class="sub-container-content"></div>
</div>
<div style=""></div>
</div>
<div style="clear: both;"></div>
</div>
I'm using the first and last div in container-content-wrapper to add rounded corners using css, like so:
.container-content-wrapper>div:first-child { /* rounded corners top */
width: 930px;
height: 16px;
background: url(../Images/top-rounded-corners.png) top no-repeat;
}
.container-content-wrapper>div:last-child { /* rounded corners bottom */
width: 930px;
height: 33px;
background: url(../Images/bottom-rounded-corners.png) top no-repeat;
}
In some cases I need to change the bottom background image using jQuery / JavaScript have failed miserably so far.
I've tried using:
$('.container-content-wrapper>div:first-child').css('background', 'some other link');
Also, adding another class that points to another image does not work.
How can I override the defined :last-child style defined in the stylesheet using jQuery?
$('.container-content-wrapper>div:first-child').css('background', 'some other link');
That selector is fine with your markup. It will select that first div which is a direct ascendant from .container-content-wrapper. So that is not your problem.
CSS selectors have no reference to jQuery selectors, so you cannot "overwrite" them. It looks like your some other link is wrong here.
Actually I initially made a mistake in targeting the div whose style needs to be replaced. It was just a matter of making the correct selection.
For reference, I have solved it by using:
$('.container-content-wrapper:has(.sub-container-content)')
.addClass('container-content-wrapper-for-sub');
where container-content-wrapper-for-sub has this style and is defined below .container-content-wrapper>div:last-child
.container-content-wrapper-for-sub>div:last-child {
/* rounded corners bottom for subsection */
background: url(../Images/bottom-rounded-corners-extra-gray.png);
}