Reputation: 50231
I have a small one-level CSS flyout menu (well, technically it's an expanding element). It is absolutely positioned at the bottom left of a parent absolutely-positioned element that is fairly narrow. See the second h1
element below:
<div id="controls">
<h1>Controls 1</h1>
<h1 id="size" class="poplinks button">
Size
<a href="#" class="button selected" title="small"><img src=""></a>
<a href="#" class="button" title="medium"><img src=""></a>
<a href="#" class="button" title="large"><img src=""></a>
</h1>
</div>
This is very simply turned into an expanding menu/flyout like so:
.poplinks:hover {
width:auto;
}
.poplinks a {
display:none;
}
.poplinks:hover a {
display:inline-block;
}
This results in the following button-like element:
The h1
has style width:48px;
, and there is also a style rule to apply width:auto;
to the h1
element upon hover, so it should be able to widen. However, upon hovering, the submenu is being forced to stay no wider than the parent element's width, when I'd like it to extend to the right (out of the parent's containing box).
What I want to see (obtained by moving the element outside the parent, but I would like it to remain inside for inheriting styling and so when I move the menu bar from the left to the top, it follows automatically):
Is this possible? Do you have any recommendations?
See this in action for yourself in a JS Fiddle.
Note: I plan for this to work in Firefox, Chrome, and IE 8. I am doing the main styling in Firefox & Chrome and when basically done, will add conditional CSS to get IE to work right and look as close as I can.
The reason I am positioning the parent menu absolutely is that I'm building an application-like page for displaying images. The page will be hosted within a parent Windows application and doesn't need a lot of identifying information: just to display the desired images. I chose to make the menu absolutely positioned rather than using inline-block or floats or some other method to get my menu columns into place (there are two). However, it doesn't have to be this way. If you have a suggestion for an alternate layout or strategy, I am all ears.
Upvotes: 11
Views: 22576
Reputation: 31365
I'm writing this answer because I might need it again in the future.
Although I've found this in the selected answer, it also mentions lots of other details asked by OP, and that somehow ended up hiding what was the important part to solve my problem.
What did the trick for me was the: white-space: nowrap
.
I needed this for a dropdown component, which I think is a common use case.
The code below uses React
and styled-components
.
const styled = window.styled;
const LS = {};
LS.DropdownButton_DIV = styled.div`
position: relative;
width: 150px;
height: 30px;
display: flex;
align-items: center;
padding-left: 8px;
border: 1px solid silver;
user-select: none;
cursor: pointer;
margin-bottom: 100px;
`;
LS.Dropdown_DIV = styled.div`
position: absolute;
left: 0;
top: 100%;
display: ${props => props.open ? "block" : "none"};
`;
LS.DropdownItem_DIV = styled.div`
display: flex;
padding-left: 8px;
border: 1px solid silver;
/* THIS IS WHAT SOLVES THE PROBLEM */
white-space: ${props => props.noWrap ? "nowrap" : "initial"};
`;
function App() {
const [open1,setOpen1] = React.useState(false);
const [open2,setOpen2] = React.useState(false);
function toggleDropdown1() {
setOpen1((prevState) => !prevState);
}
function toggleDropdown2() {
setOpen2((prevState) => !prevState);
}
return(
<React.Fragment>
<LS.DropdownButton_DIV onClick={toggleDropdown1}>
Dropdown Button 1
<LS.Dropdown_DIV open={open1}>
<LS.DropdownItem_DIV>
Dropdown Item Longer Than Parent
</LS.DropdownItem_DIV>
</LS.Dropdown_DIV>
</LS.DropdownButton_DIV>
<LS.DropdownButton_DIV onClick={toggleDropdown2}>
Dropdown Button 2
<LS.Dropdown_DIV open={open2}>
<LS.DropdownItem_DIV noWrap={true}>
Dropdown Item Longer Than Parent
</LS.DropdownItem_DIV>
</LS.Dropdown_DIV>
</LS.DropdownButton_DIV>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById("root"));
* {
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<script src="//unpkg.com/[email protected]/dist/styled-components.min.js"></script>
<div id="root"/>
Upvotes: 4
Reputation: 152976
First, your #controls
need overflow:visible
. Then, #size
should be given an explicit left
instead of right
. And finally, .poplinks
needs white-space: nowrap
to prevent the wrap.
Upvotes: 22
Reputation: 5483
Two ways: you can either hardcode an absolutely defined width, or you can do a relative width that is greater than 100%. Width of 100% will be 100% of the containing div (as long as that div has a defined width). If this div has an absolute width, meaning it is defined with pixels instead of percentages or em
s, then you can simply make the hover css wider than the parent div. For example, if your parent div is 100px wide, the hover on the child should be 200px wide or 200% or something like that.
Upvotes: 0