How to make text float over column when moused over? - html

I want to make some text float over the column edge when I mouse-over it, just like my IDE does:
Here's what I've got so far.
I can get it to float over the edge if I change the element positioning to absolute but then it doesn't "take up any space".
Also, I wouldn't mind having the border around the floated bit either.
Anyone have any ideas how to accomplish this?

I've found two ways to support this. The first requires you add span tags inside each li but it seems to be working across all browsers. The second works with the markup exactly as you have it, but doesn't work in chrome and safari.
All browsers:
http://jsfiddle.net/vkBqg/1/
This solution is extremely simple and basically comes down to:
li {
white-space: nowrap;
overflow-x: hidden;
width: 150px;
}
li:hover {
overflow-x: visible;
}
All but webkit-based browsers (chrome,safari):
http://jsfiddle.net/aeARH/1/
This is much hackier and requires you to changing the width and display type of the li, then forcing it to break line. The li:hover looks something like this:
overflow-x: auto;
width:auto;
content:"\A";
display:inline;
The take away in both of these should be position:absolute doesn't work well when you're trying to preserve the natural ordering among elements.

I have had a go at it and have come up with a solution which does not require any mark up changes at all, I have done some testing and it seems to work in Chrome 26, Safari 5.1.7, Firefox 20, IE10, IE10 in IE9 mode and IE10 in IE8 mode, it looks the same in all of these browsers and browser modes, it starts to break when using IE10 in IE7 mode.
It looks like this:
Basically what I've done is setting float:left on the li and then width:auto on li:hover, this ensures that the text floats over the column edge.
Then to add the border, I'm rendering a pseudo-element directly after the li, which inherits the width of the preceding li. Then I've set its borders, margins, heights and line-heights to position this pseudo-element over the top of the preceding li. I've set the margin-left to 150px to ensure it only shows up behind li's which exceed the width of the column.
To add some space at the right I have changed the white-space: no-wrap to white-space: pre, which will preserve some added white space inside the li (if it is added, it is not a requirement, I did add it to make it look a little prettier).
Here's a jsFiddle.
Here's the HTML:
<div>
<ul>
<li>some really long text </li>
<li>some text that doesn't fit into the column width </li>
<li>yeah dude, this is sample text </li>
<li>woot woot! double rainbows </li>
</ul>
</div>
And here's the CSS:
li {
white-space: pre;
overflow-x: hidden;
background-color: #f2f2f2;
line-height: 21px;
width: 150px;
float: left;
clear: both;
}
li:hover:after {
content:'';
height: 19px;
margin: -21px 0px 0px 150px;
border-width: 1px 1px 1px 0px;
border-style: solid;
display: block;
}
li:hover {
width: auto;
}
div {
width:155px;
border-right: 3px solid;
background-color: #f2f2f2;
}
ul:before, ul:after {
content:' ';
display: table;
}
ul {
list-style: none;
padding: 5px 0 5px 5px;
margin: 0;
}
ul:after {
clear: both;
}
body {
margin: 0;
padding: 0;
}
UPDATE
I have included the Micro clearfix hack on the div, now it adjusts its height based on its contents instead of it having a fixed height.
UPDATE 2
The problem with scrolling is that the width of the containing element is actually changing when setting width:auto on the child elements, since the scroll bar is on the right, it keeps moving around. I've tried using an extra wrapper div, but it seems that it is impossible to float stuff over the top of a scroll bar, from anywhere inside the element that creates the scroll bar. The only way I can get it to scroll is by setting overflow:hidden on the ul and then using the jQuery ScrollTo plugin to scroll up and down inside the ul.
Example jsFiddle with scrolling

Related

Collapsing margin alignment in Firefox

TLDR: this codepen works fine in Chrome, but the alignment is off in Firefox.
I'm building a jQuery plugin which modifies a text input to give it a dropdown button on the left. In order to get the positioning right, I add a wrapper div, which is the same height as the input, so the button can be absolutely positioned on top of the input, and yet still have the same height:
#wrapper {
position: relative;
}
#overlay {
position: absolute;
top: 0;
bottom: 0;
width: 30px;
}
This works fine until the input has vertical margin: then the container grows to include the margin, and so the dropdown button grows with it. My solution to this was margin collapsing: I gave the input display:block which meant that the container ignored it's margin. All good.
input {
margin: 20px 0 40px; /* testing */
display: block;
}
But now the problem is that by default, inputs are inline elements e.g. you might want to have a submit button next to the input. So I wrapped the whole thing in a container div with display:inline-block, so another inline element like a button can happily sit next to it.
#container {
display: inline-block;
}
This works fine in Chrome, but has weird alignment issues in Firefox when there's any vertical margin on the input. Below I've added the final markup. There's also a codepen link at the top.
<div id="container">
<div id="wrapper">
<input>
<div id="overlay"></div>
</div>
</div>
<button>Submit</button>
Edit: the point is that this is a plugin and I'm trying to work with the user's existing markup and CSS e.g. they have this markup:
<input><button>Submit</button>
and their existing CSS has vertical margin on the input, and I want them to be able to just initialise my plugin on the input and it just work, without forcing them to change their markup/CSS. Now because the plugin needs to add lots of markup around the input (for the overlay and the dropdown list), I wrap it all up in a container div. This container div is the limit of our reach (and does not include the button element, or anything else they choose to put next to their inputs).
To fix this, you'll need to define a line-height in your parent div#test2. Without it, different browsers will give it different values. This will cause Firefox to cause this weird result.
Now, the line-height isn't the only problem, also the vertical-align's baseline value will generate a different result for inline elements than it is for inline-block elements that have a different height than the surrounding inline content. To fix this, change the value to top for the #container element (since that's the inline-block element).
The final result would have the following changed (only pasting the parts that changed):
#test2 {
background-color: green;
line-height:70px;
#container {
// replicate the inline nature of the input
display: inline-block;
vertical-align:top;
}
//the rest of the #test2 nested code
}
That would look like this.
Reply to comment
I've made something that does work by the requirements set. Since you said the extra code (so the divs around the input) are made by the plugin itself, I've taken the liberty of changing that a bit to make this work.
The way it can work quite easily is just not using inline-blocks at all, and sticking with the inline elements. This would change the styles to the following:
#container {
// replicate the inline nature of the input
display: inline;
}
#wrapper {
display: inline;
position: relative;
}
input {
// you'll want to make sure the typed text doesn't appear behind the overlay
padding-left:35px;
}
#overlay {
position: absolute;
top: 0px;
bottom: 0px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
Notes:
I didn't bother making the overlay cover the full height of the input, since your plugin would just make it a flag anyway. To make it cover the full height, just set negative top and bottom styles on the overlay, equal to the computed padding-top and padding-bottom (resp.) on the input. In this case, you'd have to change them to top:-5px;bottom:-5px;. (you can get the computed style via jQuery's $(input).css('padding-top'))
You could actually also remove the whole #container from it, since the only style it has now is display:inline which really doesn't add anything to the whole thing.
I've added a padding-left to your input, because otherwise you'd have to type behind the overlay, which is just silly.
Is the HTML generated by the plugin and it needs to stay exactly the same? I'm not sure I can figure out exactly why the second example is not working, but you seem to have too many div elements there. You could make since simpler:
HTML
<div id="test1">
<div id="wrapper">
<input>
<div id="overlay"></div>
<button>submit</button>
</div>
</div>
SCSS
input, button {
border: 1px solid black;
padding: 5px;
}
input {
display: inline-block;
padding-left: 35px;
}
#test1 {
background-color: yellow;
padding: 20px 0 40px 0;
#wrapper {
position: relative;
#overlay {
position: absolute;
top: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
}
Codepen example
I've removed the margin, and instead used padding on the parent, it achieves the same thing. You'll also want some padding-left on your input field so the entered text doesn't disappear behind your overlay div.
EDIT: In case you are unable to change the markup:
SCSS:
#test2 {
background-color: green;
#container {
// replicate the inline nature of the input
display: inline-block;
padding: 20px 0 40px 0;
}
#wrapper {
// this is just here to be display:block and ignore the margin on the input
display: block;
position: relative;
}
input {
// tell parent to ignore margin
//display: block;
margin: 0;
}
#overlay {
position: absolute;
top: 1px;
bottom: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
codepen demo
Removed the block and margin declarations from the input field, and moved the spacing to padding of the #container element.
"Disclaimer": Let me just start by saying that I did not find exactly what is causing the problems in Firefox, but I did think of an alternative way you could do it.
The way this works in both Firefox and Chrome is just to use the exact same HTML as you used for your #test1, but on top of that, also using the CSS :before pseudo-element (instead of using the #container and #wrapper). The code I used was:
#test2 {
background-color: green;
position:relative;
&:before {
content:"";
display:block;
position:absolute;
left:1px;
top:1px;
bottom:1px;
margin:20px 0 40px 0;
width:30px;
background:#00C2FF;
}
}
demo
The way this works is to simply position the :before overlay on exactly the same place as the divs previously were. As you can see, I've used most of the same styles as you did, but instead, I've put them on the :before pseudo-class.
Other answers don't know why it doesn't work on Firefox. Well, I think that Firefox has the right behavior and it's a Chrome problem.
In short, you want to align an input with a button. But the input is inside a wrapper. Then, you can use vertical-align to control the vertical aligning between the wrapper and the button, but not between the input and the button.
Here you can see an screenshot with different vertical-align:
See the code.
If you want to align the input and the button (last case in the image), you have a problem, because any of the keywords you can use with vertical-align does that. Only in case that input's top margin and bottom margin are equal, then vertical-align: middle works.
But in general, you have have another solution: vertical-align also accepts a <length> value.
And, to get a perfect alignment, you should use the formula
vertical-align: -(input bottom margin)
Or, if you want to align them even if the button has a bottom margin, then
vertical-align: -(input bottom margin) + (button button margin)
The code formula above works with inline-block <div>, but not with <buttons>.
The formula must be fixed to
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
In your example
(Input bottom margin) = 40px
(Input offsetHeight) = 31px
Then, you need
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
Demo
I could achieve it with the following.Codepen You will have to know the css applied to input and apply it to button as well
button{
position:absolute;
margin-left:5px;
}
input, button {
display: inline-block;
margin: 20px 0 40px 0;
}
please update below in your code.
input, button {
border: 1px solid #000000;
margin: 20px 0 40px;
padding: 5px;
vertical-align: top;
}
hope it will work
http://codepen.io/anon/pen/Isycu

Where to apply the clearfix class

So I'm having a problem with the last paragraph apparently not clearing and slipping into the middle of the h1 and nav. But when I put a div with a clear:both property before the paragraph it appears to work.
Bear with my fiddle, please.
I used a purple background to represent the image replacement technique that I learned from nettuts.
The clearfix part is a class named "group", the CSS is at the bottom.
Also if I remove the display:block; from h1 > a the layout breaks so a follow up question is, what elements should I float and where should I apply the clearfix.
The problem you are seeing arises because the clearing element is in the wrong place.
Consider your CSS:
h1 {
margin: 0;
float: left;
background: red;
text-indent: -9999px;
border: 1px dashed cyan;
}
nav {
height: 44px;
margin: 0;
float: right;
background: black;
border: 1px dashed cyan;
}
.group:after {
content:"x";
display:table;
clear:both;
background-color: cyan;
}
You have h1 floated left and nav floated right, and then you have your p block with your text (not floated).
The p content wraps around the two floated elements as expected unless you add the clear:both rule to p as pointed out earlier.
The clearing element has to appear in the DOM after the nav element.
In this example, you apply .group to nav, which generates content that appears after the ul block that is a child of the nav block.
The problem becomes more obvious is you set the nav height to auto and you add some borders and colors to show the edges of the various blocks.
See demo at: http://jsfiddle.net/audetwebdesign/9nGQy/
The problem can be seen as follows:
I added an x to mark the spot in your generated content for the clearing element, which appears within the nav block.
Try:
p{
clear:both;
}
It should work for you depending what the outcome is you are after.

html/css: white spaces/collapsed container in horizontal list

I'm trying to create a horizontal menu for my webisite. It's not that difficult, but I'm running into two problems, which brake my design.
I can do it in two ways:
1). by setting
#menu li {
display: inline-block;
}
like I did here: http://jsfiddle.net/l0ner/HPpgG/.
It works and looks like I want but there is a white space between each element, which breaks the design. I could remove the space by putting all list elements in one line, but it's not exactly an elegant solution.
I know I could set the <ul> font size to 0, and then restore it in <li> but it feels too much like a dirty hack to me, and I'd like to keep the css 'magic' minimal.
How do I remove those spaces?
2). by setting
#menu li {
display: block;
float: left;
}
Like I did here: http://jsfiddle.net/l0ner/HPpgG/1/
But like this the <div> container collapses and I loose the white background for the menu, which makes whole thing unreadable.
How I can make the container uncollpased?
Here is the working jsfiddle
#menu ul {
margin: 0;
padding: 0;
overflow:auto;
}
#menu li {
float: left;
list-style:none;
}
You need to set the overflow of the ul to auto or hidden
For your first example, the white space in between the li elements is literally caused by white space in your HTML - the line breaks in between your </li> and <li> tags. If you remove this, the white space will go away.
Alternatively, for your second example, you can stretch the parent element to 'clear' the floated elements. There are a couple of ways to do this (google 'clearfix' for a few examples), but the easiest way would be to use overflow: hidden on the parent element.
Just make the 'overflow' of your <div> hidden.
#menu {
background: #fff;
color: #000;
overflow:hidden;
}
Fiddled here
You can use a pseudo-element to do a clearfix on the <ul> without additional markup
jsFiddle
#menu ul:after {
clear:both;
content:"";
display:block;
}

Wrapping a DIV around content and keeping it centered

I have a problem concerning CSS and HTML.
I'm trying to wrap a DIV around another element (an UL in this case) and having it wrap around it and at the same time keeping both centered. As an added bonus I can't set a specific width since the width of the content inside the wrapping DIV have to be dynamic (since this is basically a template).
I've tried floating, and that works as far as wrapping goes, but then the thing ends up either to the right or to the left.
I'm going a bit crazy over this, and google is no help!
Thanks in advance!
UPDATE:
Sorry about not including code or images. This is what I'm trying to do illustrated with images:
One state of the UL width
Another state of the width
The wrapping DIV can't stretch the full width of the container. It has to wrap around the UL.
The dark grey is the DIV around the UL. I need the DIV to wrap around the UL (which has a horizontal layout) no matter the width of the content, since like I said above, the content of the UL is going to by different from time to time. The text in the LIs are going to change.
I also need it to be centered. I've made it work with float left and float right, but I need it to be centered.
This is the code I'm currently using for the container DIV and the UL and LI elements:
#container{
height: 100px;
width: 500px;
font-size: 14px;
color: #grey;
display: table-cell;
vertical-align: middle;
}
#container ul{
text-transform: uppercase;
text-align: center;
font-weight: bold;
}
#container li{
background: url(checkmark.png) center left no-repeat;
display: inline;
padding-left: 20px;
margin-right: 5px;
}
#container li:last-child{
margin-right: 0;
}
UPDATED
I got it. Is it this you were looking for?? http://jsfiddle.net/vZNLJ/20/
#wrapper {
background: #ccc;
margin: 0 auto; /* to make the div center align to the browser */
padding: 20px;
width: 500px; /* set it to anything */
text-align: center;
}
#wrapper ul {
background: #aaa;
padding: 10px;
display: inline-block;
}
#wrapper ul li {
color: #fff;
display: inline-block;
margin: 0 20px 0 0;
}
#wrapper ul li:last-child {
color: #fff;
display: inline-block;
margin: 0;
}
<div id="wrapper">
<ul>
<li>Menu</li>
<li>Menu</li>
<li>Menu</li>
</ul>
</div>
This is an old post, but what you can do now is:
<div style="display: flex; justify-content: center;">
<div style="display: inline-block;">
<input type="button" value="Example Button" />
</div>
</div>
The problem isn't wrapping the DIV around the content, but getting the content to state it's actual size, therefore pushing the DIV boundaries out. There are several things that need to be considered when tackling this issue. Not just from an existing UL or LI tag, but a DIV within a DIV.
I use custom tags to help describe layouts cleaner. Custom tags are DIV tags, thus their properties must be manipulated by CSS in order to get the proper behavior.
<layout-linear horizontal>
<control-label>Label 1</control-label>
<control-label>Label 2</control-label>
<control-label>Label 3</control-label>
<control-label>Label 4</control-label>
<control-label>Label 5</control-label>
</layout-linear>
This layout suggests that the contents .. the control-label(s) tags .. will be display in a horizontal row. To get the border for the layout-linear tag to wrap around the content of the control-label tags, there are several things to do:
layout-linear[horizontal]
{
display : block;
box-sizing: border-box;
border : 1px solid black;
padding : 1px 1px 1px 1px;
white-space: nowrap;
width : 100%;
clear : both;
text-align : center;
}
First, the box-sizing property must be set to border-box. This will force the linear-layout (DIV) tag to wrap around content. Padding, Border, Margin will insure that an empty DIV tag displays. Other tricks to make an empty DIV tag display are to use or :after { content:.; visibility: hidden; }.
If you don't want the control-label tags to wrap, adding white-space : nowrap.
I will discuss text-align when I discuss the float property of the control-label tag.
The next part requires the inner DIV tags (control-labels) to properly specify their box-sizing type and borders.
control-label
{
display : inline-block;
/* float : left; */
box-sizing: border-box;
border : 1px solid black;
margin : 5px 5px 5px 5px;
padding : 5px 5px 5px 5px;
}
Display : inline-block, causes the control-label tags to flow left to right. Display : Block, will cause the tags to stack up vertically.
Float is commented out specifically to draw your attention to the fact that float will cause the layout-linear tag shrink to its smallest box size, based on the margins, padding, and border.
To have the control-labels flow right to left, add text-align : right to the layout-linear tag. Or in this specific case, set text-align : center.
Again, box-sizing is used to tell the control-label (DIV) tag to wrap around it's content completely. Not just the text, but the edges of the box as drawn by the border, padding and margin settings.
This arrangement of CSS properties is what causes the outer and inner boxes to be rendered properly, or as expected.
Happy Coding.
You didn't supply code, but take a look at this fiddle I just setup, which might help:
http://jsfiddle.net/qXDJr/
Please let me know if I'm misunderstanding what you mean. Example code will always help for future reference.
This might help.
If you cant set the width you can just add align='center' in the div wrapping ul
<div align="center">
<ul>
<li>MenuItem</li>
<li>MenuItem</li>
<li>MenuItem</li>
</ul>
</div>

Centering left floated <li> tags inside of a container

I have a container that contains:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
As in here: http://sneakyrascal.com/gmat/conv/select-plan.html
And the CSS for the <li> is set to the left so they can be in one line. If I remove one <li> then it will add an empty space to the right. like this one: http://sneakyrascal.com/gmat/conv/select-plan-2.html
When I remove a <li> I want the other ones to be centered rather than being floated to the left. But I can't remove the float:left now that they need to be in one order. How can I get around it? I tried margin: auto; for <ul> but it didn't work.
If you're absolutely constrained to using floats to achieve this, then you'll need some way to compute what the width of the container should be given the number of elements, and somehow apply it to the container directly. Then margin:auto should work fine.
Why? Because when you float the items, the container no longer uses them to calculate its width.
As is, it appears you are applying width: 1050px directly to the container. You might want to remove this style declaration from the stylesheet, and then (if you can) dynamically insert a class-name like columns-4 or columns-5 (depending on the count) to the container, then style each class with the appropriate width.
If, however, you can use other layout methods, then you have a couple of better options:
Apply display:inline-block on the lis, like here: http://jsfiddle.net/HPeAK/
Notes:
1) ie6 won't apply display:inline-block to elements that are native blocks, like <li>, so if IE6 support is essential (yuck!), you would need to have a span inside that item and apply display:inline-block there.
2) inline-block will introduce white-spaces where they exist in the source because they are treated as inline elements.
OR:
Apply display:table on the container or ul, and display:table-cell on the <li>s, like here: http://jsfiddle.net/3efZJ/
I found that if you set your UL to have display: table, margin: 0 auto will work on that and centre it. The alternative is set the UL to display: inline-block and use text-align: center on the container div to position it. With both of these though you are going to see problems with IE7 and below. It doesn't support display: table outright and display: inline-block only works on elements which are naturally inline, of which UL isn't.
Make your container overflow: hidden:
.select-plan #container {
float: left;
margin: 0 auto 40px;
overflow: hidden;
width: 1050px;
}
Set the list as having float: left; left: 50%; position: relative; margin: 0 auto like so:
.select-plan #container ul {
float: left;
left: 50%;
margin: 0 auto;
position: relative;
list-style-type: none;
}
Give your list items right: 50% like so
.select-plan #container ul li {
background: none repeat scroll 0 0 #FFFFFF;
border: 1px solid #DBDBDB;
border-radius: 5px 5px 5px 5px;
box-shadow: 0 1px 1px #666666;
float: left;
height: 418px;
margin-right: 10px;
overflow: hidden;
position: relative;
width: 187px;
right: 50%;
}
This hack should work. It isn't ideal but hey, it's better than nothing.
you cannot use auomatic left/right margin if you don't give a value to the width of ul.
If you generate this page with a programming language, you can calculate the width of the UL element having fixed with of LI elements.
So for the second example you can set a width of 796px for UL element obtaining the effect you need.
As i can see in your css you are forcing elements to stay in different positions.
eg. #margin-top: -106px; in footer
This may lead to different appearances in different browsers. Moreover elements are overflowing.
eg. elements inside#wrapdiv.
you can add overflow: hidden; to fix that. Use firebug and hover over your page and try to fix the css issues first.
.select-plan #container ul {
margin-left: 9em;
}
It's not dynamic but it will center 4 containers.