How do I offset the anchor scroll that overlaps elements? - anchor

How to add an offset to elements hash location so my navigation bar on the top of the window will not overlap my content?
<nav id="nav">
Home
About
Contact
</nav>
<main>
<section id="home">
<h2>Welcome to example.com</h2>
</section>
<section id="about">
<h1>About us</h1>
</section>
<section id="contact">
<h2>Contact us</h2>
</section>
</main>
The simplest solution I've found on the internet is to add some margin-top or padding-top to the targeted element section{ margin-top:100px }, but this will interfere with my design and I don't want to hack using hidden elements to fix this issue.

TL;DR
window.addEventListener("hashchange", function(e){
e.preventDefault()
const navHeight = document.getElementById("nav").offsetHeight
const target = document.getElementById(window.location.hash.substring(1))
window.scrollTo(0, target.offsetTop - navHeight)
})
I sadly don't know the jQuery solution to this.
Explanation
So how does this work, we add an event listener to the window that is looking for hash changes.
We want to prevent the default browser scroll and use our own "adjusted" scroll with an offset.
If you have a sticky navigation on the top of your page that is always showing, we need to know the height of the navigation element. const navHeight = doc.getElementById("nav").offsetHeight
As next we are getting the hash location, for example.com/about.html#team we want to get the hash location without the hash symbol window.location.hash.substring(1), returns "team"
Now we need to get the target element by passing the returned hash location to the document.getElementById(window.location.hash.substring(1))` that will return the target element.
Now we do some simple math to offset the navigation element so it won't overlap your valuable content.
target.offsetTop - navHeight
As the last step, we pass the new calculated offset to the windows scroll function.
window.scrollTo(0, target.offsetTop - navHeight)

Related

How do I make the contents of a vaadin-split-layout scrolling independently?

I have the following for a polymer web application. The whole page scrolls. I would like for the contents of and to scroll independently. foo has a longer view and bar is generally able to fit in the page with maybe a little vertical scrolling.
How do I make the two contents of vaadin-split-layout scroll independently vertically?
<app-drawer-layout fullbleed force-narrow>
<app-drawer slot="drawer">
<app-toolbar>
<div main-title>Models</div>
</app-toolbar>
<section>
<div style="margin-bottom:90px;width:100%;"></div>
</section>
</app-drawer>
<app-header-layout>
<app-header slot="header" fixed effects="waterfall">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<iron-icon id="logo" src="icon.svg"></iron-icon>
<div main-title>Spliter Sample</div>
</app-toolbar>
</app-header>
<section>
<vaadin-split-layout orientation="horizontal">
<foo></foo>
<bar></bar>
</vaadin-split-layout>
</section>
</app-header-layout>
</app-drawer-layout>
Thank you for any advice.
You can style the panels of a vaadin-split-layout as any other div as the panels are in the light DOM as you can see when inspecting their examples.
Thus give them an explicit height and an overflow:auto or overflow-y:auto; to enable scrolling. The style rules be placed in your usual CSS.

iOS 7 Safari can't scroll DIV with overflow: hidden or auto

I'm working on a page with four (4) separate DIV elements that all are scrolled independently of each other. Using the answer here: `-webkit-overflow-scrolling: touch` broken for initially offscreen elements in iOS7 I was able to get most of the pages working. There are still a few pages where the DIV holding the main content cannot be scrolled vertically when a side DIV is expanded.
The page structure looks like this:
...
<div id="paneTop">...</div>
<div id="paneLeft" class="expanded">...</div>
<div id="paneCenter">
<div>
<div style="overflow: hidden;">
<div id="mainContent" style="overflow: auto;">...</div>
</div>
</div>
</div>
<div id="paneRight" class="expanded">...</div>
...
Setting the touchstart event listener on #paneCenter worked for most of the pages but those didn't have the extra layer of divs. I have tried setting the touchstart event listener on #mainContent and all the way up the chain but #mainContent will not scroll when #paneLeft is expanded even though it works when #paneLeft is collapsed and it works whether paneRight is expanded or not.
Note: this issue has only been identified on an iPad running iOS7.
This is the correct behavior. If you want it to scroll vertically but hide it horizontally, then target it specifically: overflow-x: hidden (to hide horizontal excess), and don't set anything to overflow-y. This allows for some good control over elements.

All anchor tags work except top

On this site I'm using a smooth-scroll function, which works on every link unless you try and go back home. Any suggestions?
The id "Home" refers to an fixed positioned element (the header), it's always visible so the script has no where to scroll to.
Swap Id's between <header id="home"> and <section id="intro"> to <header id="intro"> and <section id="home"> ,or you can just change your first list's item anchor to <a href="#home">that way the script has somewhere to head to.
Remove your section's padding, and apply it to a more inner element of your sections, otherwise your first section's headings will be misplaced.
Good Luck Developer!

How can I resize a jQuery Mobile page after adding elements to the DOM?

I have a jQuery Mobile (1.0.1) page with a fixed footer:
<footer data-role="footer" data-position="fixed">
Click Me!
</footer>
When I add elements to the DOM, the footer bar (which obviously shouldn't move) scrolls off the bottom of the screen - in accordance with the height of the elements added to the DOM. There's also white background between the previous end of the (grey) page and the new position of the footer bar.
If I scroll down and back up, the formatting is corrected.
I'm using Chrome, but it also occurs in Mobile Safari and IE.
The code that adds elements to the DOM is:
$("footer a").click(function () {
$("div[data-role='content']").append($("<button>Button A</button>"), $("<button>Button B</button>"), $("<button>Button C</button>"), $("<button>Button D</button>"));
$("div[data-role='content']").trigger("create");
});
What am I missing?
Have you tried calling the JQM updatelayout event?
See this page for some more info.
Try something like this:
$("div[data-role='content']").trigger("create").trigger( 'updatelayout' );

Sharing an element between jQuery UI tabs?

I'm using jQuery UI's tabs to divide content on my page. I have a 'link bar' I would like to have hang at the bottom of each tab. (The tab text will change but generally they will navigate the user left or right through tabs.)
Hosting the #linkBar div inside the first tab makes it 'look' right, inside Themeroller's border. Putting it just outside the 'parent tab' div places the links below the theme's border. I've tried creating a spacer div but it just pushes #linkBar down further.
Of course when the user switches to another tab, the link bar goes away. How is ownership of elements organized between tabs? Should I dynamically destroy the #linkBar div on the tab being navigated away from and rebuild it in the tab being navigated to? Or is there a better way to move it between them, or just manage visibility?
I would like to have the link bar follow the content on each tab as a footer, 'floating' one or two lines below the last content of each tab (rather than having it in a fixed position relative to the tab bar).
Ok ... It was simply adding the jQuery UI classes to the linkBar. Check out my working jsFiddle demo:
I moved the linkBar div out of the tabOne div and put it at the bottom of the tabs div:
<div id="container">
<div id="title">
<h1>title bar</h1>
</div>
<div id="tabs">
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
<div id="tabone">
content goes here
<br><br><br><br>more stuff<br><br><br>more stuff<br><br>
</div>
<div id="tabtwo">
content goes here...
</div>
<div id="tabthree">
content goes here...
</div>
<div id="linkBar">
<span id="leftLink"><< left link</span>
<span id="rightLink">right link >></span>
</div>
</div>
</div>
I slightly altered the linkBar style by giving it a top and bottom margin as well as hiding it by default:
#linkBar {
display: none;
margin: 10px auto;
}
Then I simply added the jQuery UI classes to the $linkBar. I slightly altered the jQuery to be more readable:
$("#accordion").accordion({ header: "h3" });
var $tabs = $("#tabs"),
$linkBar = $("#linkBar");
$linkBar.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");
$linkBar.show();
$tabs.tabs();
$('#title').click(function() {
$tabs.tabs('select', 0);
return false;
});
Note: You could just add class="ui-tabs-panel ui-widget-content ui-corner-bottom" to the linkBar div and be done with it. But, I think I like it better managed in the JS.

Resources