Angular 10: Router with anchorScrolling does not work on div with position absolute and overflow: auto - css

I am sure i must be doing something wrong but can't figure out what. Need some help/pointers.
I am using Angular 10.
I have enabled anchorScrolling in app-routing.module
const routes: Routes = [
{ path: 'docs', component: DocsComponent }
];
#NgModule({
imports: [RouterModule.forRoot(routes, {
useHash: true,
anchorScrolling: 'enabled'
})],
exports: [RouterModule]
})
export class AppRoutingModule { }
This works if the container for the jump-sections (the sections with #id where I want to scoll to) does not have property overflow:auto set , but if I set the property overflow:auto then the scrolling stops working through anchorScrolling. I can still scroll manually or by typing the url along with the fragment.
I have created a StackBlitz project to demonstrate this.
The project here is working by default
https://stackblitz.com/edit/angular-ivy-ub5k7q
However if you add
overflow:auto
to the
.sections
class in the hello.component.css you will see that the section links give at the top don't result in scroll even though the url does get updated with the correct route#fragment.
Is this an expected behavior?

I couldn't figure out why this is happening. Tried for minutes, but I could get to what I believe was your objective in the first place.
The changes I made (only in hello.component.css):
.sections{
position:relative;
top:5rem;
border:2px solid rebeccapurple;
overflow:auto;
}
I removed the height you were setting up for the position property which had the value 'absolute'. I also changed the value from the position property to be relative.
It is working with the position set to be 'absolute', but whenever you apply values for width and height it stops working.

According to this answer, I propose you a solution without fragment, but which works.
First change your a element as follow <a (click)="toSection('1')">Section 1</a> and for each section change the number with the corresponding one.
Then in your component add this method
toSection(section: string){
const elem = document.getElementById("section-"+section);
const topPos = elem.offsetTop
document.getElementById('sections').scrollTo({top:topPos-10, behavior:'smooth'})
}
With topPos-10, you got something a bit more beautiful because the top of the div is not stick to the section title.
PS : This way, in my opinion, it's a little bit better because you don't have your URL with #section at the end.
Here is the stackblitz.

Related

Why is my nested web component adding vertical space in Lit?

I have a weird issue where when I add padding-left: 32px to an element, vertical space gets added. If the CSS says 0, and I add the space manually in Chrome debugger, the vertical space isn't there. This is only happening with nested components. I'm not sure if I'm misusing something or if I have found a bug.
I have code like this:
<cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Not Nested A</cai-setting-row
><cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Not Nested B</cai-setting-row
>
<cai-setting-row-account></cai-setting-row-account>
The render of cai-setting-row-account is just the same markup:
render() {
return html`<cai-setting-row
class="itemGroupMiddle doubleIndent"
data-type="A"
>Nested A</cai-setting-row
><cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Nested B</cai-setting-row
>`;
}
It renders like this:
The "Not Nested" elements look right. The "Nested" ones have extra space and you can see a weird border on top that is the distance of the padding.
I have a functioning sandbox here:
https://studio.webcomponents.dev/edit/8u0cg76BNEiSoHXQT8by/
I misunderstood how class is used on a custom component. Doing <my-component class="foo"> adds foo to the :host. My code in sandbox needed to change the magic of const parentClass = this.getAttribute('class') ?? ''; to const parentClass = this.getAttribute('itemClass') ?? '';, such that I wouldn't accidentally be applying classes to the :host and the intended element.

CSS Styling Angular 2+ (pain in the butt)

Ok, i am new to Angular 4. I am having issues with styling the application properly. I went ahead and added a background image to the body, this worked as expected, then added a component that would display content and it looked as expected.
I added a second component different route but for this one I do not want the body to have the background image at this point i am not sure what is the best practice.
I read a few articles and some say that you can have a different style for the body at the component level by adding a body style override in the styleUrls. I did this but everytime i went from say /myroute/page2 to myroute/page1 the background sticked to what i set for myroute/page2 while it should show the body image for /myroute/page1. I am also using ViewEncapsulation set to None (maybe this is the issue)?.
Also this is my setup and may be wrong too
index.html has something like this:
</head>
<body>
<app-root></app-root>
</body>
</html>
then my app.component.html has this:
<app-navigation></app-navigation>
<router-outlet></router-outlet>
<app-footer></app-footer>
and then i have my welcome.component.html that has a section
<section id="hero">
<div>
</div>
</section>
Now the component above shows the background set correctly, but if I navigate using something like
this.router.navigate(['/page2']);
the background stays the same as in my welcome component. If i refresh on /page2 the right background now shows up.
UPDATE:
Ok i gave up on showing the background on the second component, i wanted without background image, but want to keep the one in the first component. So i removed the ViewEncapsulation from all of them but now if I move the body {} to the first component it does not show it for some reason (I made sure it has the right path). Is there a better fix than removing it by using the DOM?. What is the best practice?.
You need to set style class on ngOnInit and remove it on ngOnDestroy.
constructor(private renderer: Renderer2) {
}
ngOnInit() {
this.renderer.addClass(document.body, 'your_class');
}
ngOnDestroy() {
this.renderer.removeClass(document.body, 'your_class');
}
This worked for me, pls try. In your component1,
ngOnInit() {
document.body.style.background="url(https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSu5rIAFQkkswZLuwAUCXZqc_8bBROGkGgmZP5bmGk57sRKXWJMEg)";
}
ngOnDestroy() {
document.body.style.background="";
}
In your component2,
ngOnInit() {
document.body.style.background="url(http://gkreading.com/wp-content/uploads/2017/03/awesome-kid-in-the-grass.jpg)";
}
ngOnDestroy() {
document.body.style.background="";
}
Hope this helps.

React Routes - different styling on body css tag

I have two routes on my React app: /a and /b.
For /a, I want the body css tag to have a background-color: red;.
For /b, I want the body css tag to have a background-color: blue;.
Both components a and b live in different .JSX files, and both import their own main.scss file which defines their own respective body background-color.
However, since the entire app is compiled into the body tag, there seems to be a conflict, and only one of the body tags is respected for both routes.
<body>
<script src="bundle.js" type="text/javascript"></script>
</body>
The reason I want it on the body tag and not just a container div is that I want the background-color to be visible when I scroll outside the bounds of the page (the bounce effect on Mac and iOS).
What's the proper way to do this?
That's happening because when you import your styles in your component without CSS Modules, the styles are global so your body style is defined two times (you can see all the styles in the <head> tag).
You can fix that by setting the background color in your component componentDidMount() method.
Example
componentDidMount(){
document.body.style.backgroundColor = "red"// Set the style
document.body.className="body-component-a" // Or set the class
}
or, if youre using functional components you can do the same with useEffect...
useEffect(() => {
document.body.className = 'class-name';
}, []);
I agree with what QoP said but, as an add on to that, you should also make sure to use componentWillUnmount to set it back to whatever it normally is outside that component.
for example:
if normally for the whole application text-align is left but for one component you want it to be center, but after the component it needs to return to being left, you will do the following:
componentDidMount() {
document.body.style.textAlign = "center"
}
componentWillUnmount(){
document.body.style.textAlign = "left"
}
Add this code
componentDidMount(){
document.body.style.backgroundColor = "white"
}
Hope to help.

Adjust Angular UI Boostrap Modal Size/Width

Essentially what the title says - need to make this wider. Tried several solutions, neither work. Note that the "backdropClass" is applied perfectly and works, but the windowClass doesn't, nor the "size" option. I have tried them independently, nothing. CSS is in the same folder as the working backdrop class"
$modal.open({
templateUrl: 'myTemplate.html',
controller: 'controllingControllerCtrl',
backdrop: 'static',
backdropClass : 'blackBackgroundModal ' +
'blackBackgroundModal.fade blackBackgroundModal.fade.in',
windowClass: 'resizeModalWindow' +
'resizeModalDialog',
size: 'sm'
});
}
}
CSS:
.resizeModalWindow .resizeModalDialog {
width: 5000px;
}
What needs to be done for at least the "size" option to register - I don't really need custom widths.
Edit: Forgot checked links!
Checked this Q first
Then this
And of course docs
bootstrap css has media queries defining the width of a modal based on screen size. to globally overwrite them use !important
like this
.modal {
size: 5000px !important;
}
You should have white space between those two classes will recognize by the css rule.
windowClass: 'resizeModalWindow ' +'resizeModalDialog',
^^^added space here
Add this to your CSS:
.resizeModalDialog .modal-dialog{
width: 5000px;
}
Add the property where you instance the modal
windowClass:'resizeModalDialog',
windowClass will not resize another way.

bootstrap 3 - not pushing footer to the bottom of page

I received a task at work to create some mini-webpage layout with bootstrap. I decided to base on already done layout (Amoeba). Here is the preview: Amoeba bootstrap link
Well, on localhost almost works except one thing - footer. Just take a look on provided link and then: click Portfolio (from navigation) and then filter the gallery by Photography.
When you will scroll down you will see ugly space. And this is my issue. I dont want that. So i thought that I need a footer OR portfolio div class which will automatically resize to proper size. BUt I dont how how to achieve that. Any tips?
You need only to change the code of modernizr slightly. Change forceHeight to false and will work good.
if (Modernizr.mq("screen and (max-width:1024px)")) {
jQuery("body").toggleClass("body");
} else {
var s = skrollr.init({
mobileDeceleration: 1,
edgeStrategy: 'set',
forceHeight: false,
smoothScrolling: true,
smoothScrollingDuration: 300,
easing: {
WTF: Math.random,
inverted: function(p) {
return 1-p;
}
}
});
}
Im not sure why, but your body element gets some height inline styling. Anyways here is the solution of your problem:
body {
height:100% !important; // inline styles, so you need to add "!important" here
position:relative;
}
#footer {
position: absolute;
width: 100%;
bottom: 0px;
}
You can also add wrapper div if you don't want to add position:relative and height:100%!important properties to your body element. Just see how it works and choose a better option for you.

Resources