83

I have a positioned div whose content can be too long so scrollbars appear (overflow:auto set). It functions as a dialog box in an ajax app. I want to fix a close button on it's right top corner so when the user scrolls the div it won't scroll away.

I tryed it with position:fixed; right:0; top:0 but it placed the button on the right top of the page not in the div (in firefox).

Is it possible to do this button placement using CSS only without hacking with the offsetWidth/Height in js on every scroll event?

ps: the div's height and width is not a fixed value it depends on the content's size and the browser window's size. User can also resize it if he want.

5
  • 1
    It might be worthwhile to consider using a div with a fixed-position background image for the button. Commented Nov 10, 2013 at 19:48
  • 1
    @NickM seems like a good idea but how would you click the button then? Commented Nov 7, 2014 at 8:51
  • @ithil So long as the height and width of the div are set to match that of the background image, it should be clickable. As far as handling the click, that depends on whether you're using plain HTML or JS. If it's just HTML, you could wrap the div in an a tag with an href (or even just use an a tag instead of a div and set it as display: inline-block). If it's JS, you can listen for a click on the div. Did I understand your question correctly? Commented Nov 7, 2014 at 19:10
  • @NickM yes I believe you did thanks, but the height and width will be "set to match" using JS too I guess? as in the OP question "the div's height and width is not a fixed value", that's why I was wondering Commented Nov 7, 2014 at 20:18
  • @ithil I see. I missed that part. In that case, I think you're right that some JS would have to handle the sizing of the div. Commented Nov 7, 2014 at 22:21

10 Answers 10

88

You can use the position:fixed;, but without set left and top. Then you will push it to the right using margin-left, to position it in the right position you wish.

Check a demo here: http://jsbin.com/icili5

Sign up to request clarification or add additional context in comments.

7 Comments

@Sotiris can you provide a reference that explains why this should work? Why must browsers position a fixed element in this way when top and left are not specified? stackoverflow.com/questions/8712047/…
I wrote the most convoluted JS till I stumbled on this. Nice.
this is not the desired behavior
I agree this is not the answer. it doesn't handle dynamic width containers as stated in the question.
Well it's the first time I've seen so many people totally misunderstand a question on this site.
|
15

The current selected solution appears to have misunderstood the problem.

The trick is to neither use absolute nor fixed positioning. Instead, have the close button outside of the div with its position set to relative and a left float so that it is immediately right of the div. Next, set a negative left margin and a positive z index so that it appears above the div.

Here's an example:

#close { position: relative; float: left; margin-top: 50vh; margin-left: -100px; z-index: 2; } #dialog { height: 100vh; width: 100vw; position: relative; overflow: scroll; float: left; } <body> <div id="dialog"> **** </div> <div id="close"> </div> </body> 

1 Comment

Awesome answer, got me on the path to a better solution for having an element fixed inside of a scrollable div.
7

I know this is an old post but I had the same question but didn't find an answer that set the element fixed relative to a parent div. The scroll bar on medium.com is a great pure CSS solution for setting something position: fixed; relative to a parent element instead of the viewport (kinda*). It is achieved by setting the parent div to position: relative; and having a button wrapper with position: absolute; and the button of course is position: fixed; as follows:

<div class="wrapper"> <div class="content"> Your long content here </div> <div class="button-wrapper"> <button class="button">This is your button</button> </div> </div> <style> .wrapper { position: relative; } .button-wrapper { position: absolute; right: 0; top: 0; width: 50px; } .button { position: fixed; top: 0; width: 50px; } </style> 

working example

*Since fixed elements don't scroll with the page the vertical position will still be relative to the viewport but the horizontal position is relative to the parent with this solution.

Comments

5

Position:fixed gives an absolute position regarding the BROWSER window. so of course it goes there.

While position:absolute refers to the parent element, so if you place your <div> button inside the <div> of the container, it should position where you meant it to be. Something like

EDIT: thanks to @Sotiris, who has a point, solution can be achieved using a position:fixed and a margin-left. Like this: http://jsfiddle.net/NeK4k/

2 Comments

User can scroll away the close button if I use absolute (that was my first try before tried fixed.)
Looks like everyone misread want to keep it on the screen. In that case, you must use javascript to correctly position it in relation the div in question, or use javascript to scroll it properly while using position: absolute
2

Seems, css transforms can be used

"‘transform’ property establishes a new local coordinate system at the element",

but ... this is not cross-browser, seems only Opera works correctly

2 Comments

It works in Chrome and Firefox now. Here's an example. codepen.io/anon/pen/ZOqrYo
Thanks @PatrickMcElhaney for your example, this is the solution I was looking for :)
2

Try position:sticky on parent div of the element you want to be fixed.

More info here: http://html5-demos.appspot.com/static/css/sticky.html. Caution: Check for browser version compatibility.

Comments

1

I achieved to have an element with a fixed position (wiewport) but relative to the width of its parent.

I just had to wrap my fixed element and give the parent a width 100%. At the same time, the wrapped fixed element and the parent are in a div which width changes depending on the page, containing the content of the website. With this approach I can have the fixed element always at the same distance of the content, depending on the width of this one. In my case this was a 'to top' button, always showing at 15px from the bottom and 15px right from the content.

https://codepen.io/rafaqf/pen/MNqWKB

<div class="body"> <div class="content"> <p>Some content...</p> <div class="top-wrapper"> <a class="top">Top</a> </div> </div> </div> .content { width: 600px; /*change this width to play with the top element*/ background-color: wheat; height: 9999px; margin: auto; padding: 20px; } .top-wrapper { width: 100%; display: flex; justify-content: flex-end; z-index: 9; .top { display: flex; align-items: center; justify-content: center; width: 60px; height: 60px; border-radius: 100%; background-color: yellowgreen; position: fixed; bottom: 20px; margin-left: 100px; cursor: pointer; &:hover { opacity: .6; } } } 

Comments

0

If your close button is going to be text, this works very well for me:

#close { position: fixed; width: 70%; /* the width of the parent */ text-align: right; } #close span { cursor: pointer; } 

Then your HTML can just be:

<div id="close"><span id="x">X</span></div> 

Comments

0

position fixed but relative to parent-div

#parent-div { position: *either static or relative, doesn't matter* width: 1024px; // for example height: 300vh; // for example } #sticky-div { // should be div position: sticky; bottom: 40px; width: 30px; // your-element's width or larger height: 30px; // your-element's height or larger margin-top: -40px; // to compensate "bottom" margin-left: auto; margin-right: 20px; // substitution for "right" property z-index: 10; } #your-element { width: 30px; height: 30px; background-color: red; } <div id="parent-div"> <div id="sticky-div"> <whatever id="your-element" /> </div> </div> 

Comments

0

Not sure if it's different from the other solutions, but this is how I understand the fixed position without any top, left, etc:

You place your element wherever you want using a wrapper, and then on the element itself, you just use "fixed" position. This will "freeze" the element.

This is only working if you make sure you don't have a global scrollbar on the body.

So this should work for the use case of the question.

<body style="height :80vh; display:grid;place-items:center"> <div style="height:150px; width:150px;background:grey;overflow-y:auto"> <div style="height:2000px;position:relative"> <div style="position:absolute;top:0;right:25px;"> <button style="position:fixed"> x </button> </div> <div>stuf</div> <div>stuf</div> <div>stuf</div> <div>stuf</div> <div>stuf</div> </div> </div> </body>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.