Don't affect positioning of other elements on border-width changes - css

I'd like to change border-width of a circle on hover without affecting the positioning of other elements.
It will be more clear with this jsFiddle.
HTML
<span class="menu"><i class="cercle"></i>Foo</span>
<span class="menu"><i class="cercle"></i>Bar</span>
CSS
.menu{
margin-right: 10px;
cursor: pointer
}
.cercle{
border-radius: 16px;
margin-right: 5px;
vertical-align: middle;
width: 16px;
height:16px;
display:inline-block;
border: 5px solid #ff9c08
}
.menu:hover i{
border-width: 3px;
transition:border-width .1s
}

There are a couple of different ways you can go about achieving the effect you desire.
1. Using box-sizing: border-box:
Normally, neighbouring elements are affected by the changing an element's border-width property, because the elements are relatively positioned and the space each one occupies changes when the border-width changes. Using box-sizing: border-box ensures the width of the border is included in the dimensions of the element.
.cercle {
box-sizing: border-box;
}
2. Using box-shadow:
An alternative would be to use box-shadow property, instead, to imitate the visual appearance of a border but without its particular behaviour. The shadow of an element doesn't affect neighbouring elements when modified, so it's another good option to consider when trying to achieve the effect you desire.
.cercle {
box-shadow: inset 0 0 0 4px #ff9c08;
}
.menu:hover > .cercle {
box-shadow: inset 0 0 0 2px #ff9c08;
}
Check out more about the browser compatibility of box-sizing and box-shadow to see which suits you better. An updated version of your jsfiddle can be found here and a snippet just below.
Snippet:
.menu {
margin-right: 10px;
cursor: pointer;
}
.cercle {
width: 16px;
height: 16px;
display: inline-block;
margin-right: 5px;
vertical-align: middle;
border-radius: 16px;
}
#ex1 .cercle {
border: 4px solid #ff9c08;
box-sizing: border-box;
}
#ex1 .menu:hover i {
border-width: 2px;
transition: border-width .1s;
}
#ex2 .cercle {
box-shadow: inset 0 0 0 4px #ff9c08;
}
#ex2 .menu:hover .cercle {
box-shadow: inset 0 0 0 2px #ff9c08;
transition: box-shadow .1s;
}
<div id = "ex1">
<span class="menu"><i class="cercle"></i>Foo</span>
<span class="menu"><i class="cercle"></i>Bar</span>
</div>
<br>
<div id = "ex2">
<span class="menu"><i class="cercle"></i>Foo</span>
<span class="menu"><i class="cercle"></i>Bar</span>
</div>

This is not possible without having a border already on the element as adding a border would increase the width and height of the element. The technique I prefer is to have a transparent border on non-hover state to begin with and change the colour on hover.
.menu {
border: 3px solid rgba(0,0,0,0);
}
.menu:hover {
border-color: black;
}

This actually is possible, with box-sizing.
Setting .cercle { box-sizing: border-box; } means that the width and height of the .cercle elements includes the size of the border.
As such, the size of the .cercles will shrink with box-sizing: border-box, but that's an easy fix: just up the height and width from 16px to 21px (a change of 5px, since 5px was the size of the border).
Hopefully I explained how this works okay!
See this jsfiddle for functioning code:
https://jsfiddle.net/xhanrkzy/3/

I would assume you wanted to scale it down.
I used the transform property to do this:
.menu:hover i {
/* border-width: 3px; */
transform: scale(0.95);
transition: border-width .1s
}

In general "box-sizing: border-box" is a great simple solution. Note you can set it to apply to every element by default in your style-sheet. Here's a nice article about it: https://css-tricks.com/box-sizing/ .
Be aware that using border-box and changing the border-width means there is less space inside the circle etc. That is because the border "grows inwards" when using border-box. Therefore changing the border-width can affect the position of elements INSIDE the DOM-element whose border-width you are changing. Whether you consider those to be "other elements" (as per your question) is a matter of semantics.

Related

understanding css inherited currentColor

I was curious about currentColor and how it behaves when it is inherited and/or used in other properties.
Another aspect is omitting a color value in the border-property for example which should default to the text-color.
.outer {
color: #f90;
border: 5px solid;
box-shadow: 0 0 15px;
text-shadow: 2px 2px 3px;
}
<div class="outer">
Outer Div
</div>
Nothing fancy in the above Snippet.
The shadows and the border is the same Color as the Text.
Now lets inherit the color:
.outer {
color: #f90;
border: 5px solid;
box-shadow: 0 0 15px;
text-shadow: 2px 2px 3px;
}
.inner {
color: lime;
display: inline-block;
border: inherit;
box-shadow: inherit;
}
<div class="outer">
Outer Div
<div class="inner">
Inner Div no CurrentColor
</div>
</div>
Resutls:
In IE11 & Chrome 43 only the Text-Color is lime.
In Firefox 38 on the other hand the shadows are green too. (Note not the border)
When actively setting everything to currentColor the Browsers are showing the same result by displaying only the text in lime and everything else in orange. (As you can see in the final snippet at the bottom)
/**
* playing with currentColor
*/
body {background: darkgray;} /* friendly wink */
.outer {
width: 85%;
color: #f90;
border: 5px solid;
box-shadow: 0 0 15px;
text-shadow: 2px 2px 3px;
padding: 15px; margin: 15px;
}
.outer.currentColor {
border: 5px solid;
box-shadow: 0 0 15px currentColor;
text-shadow: 2px 2px 3px currentColor;
}
.inner {
color: lime;
display: inline-block;
border: inherit;
box-shadow: inherit;
}
.inner.resetting {
border-color: currentColor;
/* text-shadow-color: currentColor; /* does not exist */
/* box-shadow-color: currentColor; /* does not exist */
}
<div class="outer">
Outer Div
<div class="inner">
Inner Div no CurrentColor
</div>
</div>
<div class="outer currentColor">
Outer Div
<div class="inner">
Inner Div with CurrentColor
</div>
<div class="inner resetting">
Inner Div with CurrentColor
</div>
</div>
Questions:
Why is there a difference with the border in Firefox when omitting currentColor
Why does inherit not use the color value on the same element?
Is there a way to use the same properties and switching the color? (for border-color there is as you can see in the example by resetting it)
Here is also a dabblet link if you want to play around with it:
http://dabblet.com/gist/587ea745c7cda7a906ee
So, a few things here:
The CSS Working Group agreed to change the meaning of currentColor between CSS Color level 3 and CSS Color level 4. In level 3, it is resolved at computed value time and the computed value is inherited; in level 4, the keyword currentColor is inherited as a computed value and it is resolved at used value time.
There were a number of reasons to make this change, though I can't find the minutes, and I've forgotten all the details. (I could find minutes at https://lists.w3.org/Archives/Public/www-style/2014Feb/0052.html discussing the change after the fact.) It makes things worse for transitions/animations, but better in a number of other cases. It slightly increases implementation complexity, but improves performance (at least in Gecko).
I think most implementations have not yet had a chance to update to the new rules in Level 4. Gecko certainly has not, though it's on my list of things to do (but not at the top).
Firefox has, for a long time (since well before currentColor existed) implemented a special internal value as the initial value of border-*-color and outline-color. (We also do the same for text-decoration-color, but haven't done so since 1998/1999.) This works like the level 4 currentColor does, so once we switch our implementation we can unify the two things, but we couldn't switch our implementation with the level 3 currentColor, since it would have been a significant performance and memory hit given that it was the initial value of the property. (Really, unifying our implementation means doing the same work that we've done for those properties for every other property that takes a color value.)
text-shadow and box-shadow, when the color is omitted, have explicitly specified the behavior for when the color is omitted as being equivalent to the way level 4 defines currentColor, even before currentColor worked that way: see the definition of box-shadow (the definition of text-shadow just points to box-shadow).
Why is there a difference with the border in Firefox when omitting currentColor
CSS's specifications for inheriting on text-shadow say it should inherit the .inner currentColor if it itself is set to inherit, but box-shadow is unspecified and looks like browsers are inconsistent on the implementation. Possible bug.
Why does inherit not use the color value on the same element?
It appears to inherit the computed value and not the inputted one. Example:
.outer {
color:red;
box-shadow: 2px 2px 2px; /* color omitted */
}
.inner {
box-shadow: inherit;
/* translates to:
box-shadow: 2px 2px 2px red; */
}
Like I said, it's faulty implementation.
Is there a way to use the same properties and switching the color? (for border-color there is as you can see in the example by resetting it)
How about explicitly duplicating instead of inheriting? This would give you the best result without resulting to SASS/LESS, imo.
.outer {
color: #f90;
}
.outer, .inner {
border: 5px solid;
box-shadow: 0 0 15px;
text-shadow: 2px 2px 3px;
}
.inner {
color: lime;
display: inline-block;
}
<div class="outer">
Outer Div
<div class="inner">
Inner Div no CurrentColor
</div>
</div>

How to get rid of small corners which appear during the transition?

Please see the example.
http://jsfiddle.net/ojLxdw6v/
Button and button container both have border-radius. Also button container has overflow: hidden.
But somehow corners are visible while transition.
I thought to add overflow: hidden to Button.
But it's no luck also. Transparent semicircles appear between container border and link background on the right and left side.
Just add overflow:hidden to the .btn and change the background color after the pseudo-elements have moved.
JSfiddle Demo
.btn{
position: relative;
z-index: 20;
display: inline-block;
padding: 9px 34px 9px;
font-size: 18px;
color: #000;
text-decoration: none;
border: 6px solid #fed37f;
border-radius: 25px;
overflow: hidden;
transition: background 0 ease 500ms;
}
.btn:hover {
background:#fed37f;
}

CSS Translate - Unexpected behaviour

I wanted a button to move down a few pixels on hover, but it comes back up again. Shouldn't it stay where it is while you're still hovering on it?
Email Me
.btn {background: #2ecc71; padding: .5em 1em; border-radius: 3px; color:white; font-size: 1.5em; text-shadow:2px 2px 2px #178345; box-shadow: 0px 1px 1px #21a559; transition: transform 0.5s ease 0s;}
.btn:hover {background: #28b865; transform: translate(0px, 3px);}
http://codepen.io/anon/pen/zICBw
The problem is inline element can't be transformed properly. If you set the transform right in normal state, you'll see the transform takes no effect. However it does have a little effect on animation, maybe because while animating, the element's display becomes inline-block (or block in some other cases, at least while being animated, the transform can take effect). After the animation completes, it returns back to inline. So the button's position is set back like as the translate transform has no effect.
Your button is actually an a element, which has inline display by default. You can simply change its display to inline-block or block and it works OK:
.btn {
/* ... */
display:inline-block;
}
Updated demo.
Why not simply transition top? You'll need to position the element, but it will accomplish the same without the reversion.
The problem with transitioning on transform is you change the plane the element occupies, which causes the hover state to no longer trigger. One way around this is to also apply a base transform state to the element.
Demo Fiddle
.btn {
background: #2ecc71;
padding: .5em 1em;
border-radius: 3px;
color:white;
font-size: 1.5em;
text-shadow:2px 2px 2px #178345;
box-shadow: 0 1px 1px #21a559;
transition: top .5s ease;
top:0px;
position:relative;
}
.btn:hover {
background: #28b865;
top:3px;
}

In Firefox, the right edge on the dropdown button on selectboxes with padding is disappearing on hover

In Firefox, if I have a selectbox with padding-top and padding-bottom set to 3px, I get a dropdown button of which the right edge will disappear when I hover over it.
Why?
HTML:
<select>
<option>one</option>
<option>two</option>
<option>three</option>
</select>
CSS:
select
{
padding-top: 3px;
padding-bottom: 3px;
}
JSFiddle
I have made some changes
select{
padding:3px 1px;
}
please have a look. hope it will help you :)
When we render a 'select' element without any css it is exactly the same as when we render a select element with 1px padding on all sides. Which means by default a select has a padding of 1px on all sides.
When we increase or decrease the padding property, we have to ensure to add the 1px right padding to maintain the default padding.
I used photoshop to measure the height and width to confirm the dimensions.
I created a fiddle to demonstrate this theory. Hope it helps.
http://jsfiddle.net/2BeVN/
So a padding-right: 1px seems to be required.
select{padding-top: 3px;padding-bottom: 3px;padding-right: 1px}
select{
padding-top: 3px;
padding-bottom: 3px;
background-color: #FFFFFF;
border: 1px solid #CCCCCC;
border-radius: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
color: #555555;
display: block;
font-size: 14px;
height: 34px;
line-height: 1.42857;
transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
vertical-align: middle;
}

When 1 px border is added to div, Div size increases, Don't want to do that [duplicate]

This question already has answers here:
Placing border inside of div and not on its edge
(15 answers)
Closed 1 year ago.
On click I am adding, 1px border to div, so Div size increases by 2px X 2px.
I dont want to get div size increased. Is there any simple way to do so?
Messy Detailed Explanation
Actually I am adding DIVs with float:left (same size, like icons) to a container-div, so all stacks up one after another, and when (container-div width is 300px) no space left width-wise so child DIVs comes in next row, so its like catalog, but because of border only selected DIV size get increased, DIV under selected DIV goes to right and creates empty space below selected DIV.
EDIT:
Decreasing Height/Width on selection, but how to increase it back. Using some 3rd party framework, so don't have event when DIV loses selection..
This is also helpful in this scenario. It allows you to set borders without changing div width
textarea {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
}
Taken from http://css-tricks.com/box-sizing/
If you don't have a border-radius change border to outline:
outline: 1px solid black;
Having used many of these solutions, I find using the trick of setting border-color: transparent to be the most flexible and widely-supported:
.some-element {
border: solid 1px transparent;
}
.some-element-selected {
border: solid 1px black;
}
Why it's better:
No need to to hard-code the element's width
Great cross-browser support (only IE6 missed)
Unlike with outline, you can still specify, e.g., top and bottom borders separately
Unlike setting border color to be that of the background, you don't need to update this if you change the background, and it's compatible with non-solid colored backgrounds.
The border css property will increase all elements "outer" size, excepts tds in tables. You can get a visual idea of how this works in Firebug (discontinued), under the html->layout tab.
Just as an example, a div with a width and height of 10px and a border of 1px, will have an outer width and height of 12px.
For your case, to make it appear like the border is on the "inside" of the div, in your selected CSS class, you can reduce the width and height of the element by double your border size, or you can do the same for the elements padding.
Eg:
div.navitem
{
width: 15px;
height: 15px;
/* padding: 5px; */
}
div.navitem .selected
{
border: 1px solid;
width: 13px;
height: 13px;
/* padding: 4px */
}
set a border on it before you click to be the same color as the background.
Then when you click just change the background color and the width will not change.
Another good solution is to use outline instead of border. It adds a border without affecting the box model. This works on IE8+, Chrome, Firefox, Opera, Safari.
(https://stackoverflow.com/a/8319190/2105930)
I usually use padding to solve this issue. The padding will be added when the border is not there and removed when it is back. Example:
.good-border {
padding: 1px;
}
.good-border:hover {
padding: 0px;
border: 1px solid blue;
}
See my code here: https://jsfiddle.net/3t7vyebt/4/
Try this
box-sizing: border-box;
Sometimes you don't want height or width to be affected without explicitly setting either. In that case, I find it helpful to use pseudo elements.
.border-me {
position: relative;
}
.border-me::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
border: solid 1px black;
}
You can also do a lot more with the pseudo element so this is a pretty powerful pattern.
Just decrease the width and height by double of border-width
You can do some fancy things with inset shadows. Example to put a border on the bottom of an element without changing its size:
.bottom-border {
box-shadow:inset 0px -3px 0px #000;
}
Try decreasing the margin size when you increase the border
I needed to be able to "border" any element by adding a class and not affect its dimensions. A good solution for me was to use box-shadow. But in some cases the effect was not visible due to other siblings. So I combined both typical box-shadow as well as inset box-shadow. The result is a border look without changing any dimensions.
Values separated by comma. Here's a simple example:
.add_border {
box-shadow:-1px 0 1px 1px rgba(0, 0, 0, 0.75), inset -1px 0 0 1px rgba(0, 0, 0, 0.75);
}
jsfiddle
Adjust for your preferred look and you're good to go!
We can also use css calc() function
width: calc(100% - 2px);
subtracting 2px for borders
You can try a box-shadow inset
something like this:
box-shadow:inset 0px -5px 0px 0px #fff
adds a white 5px border to the bottom of the element without increasing the size
.filter_list_button_remove {
border: 1px solid transparent;
background-color: transparent;
}
.filter_list_button_remove:hover {
border: 1px solid;
}
You can create the element with border with the same color of your background,
then when you want the border to show, just change its color.
In case content of your div is rendered dynamically and you want to set its height, you can use a simple trick with outline:
button {
padding: 10px;
border: 4px solid blue;
border-radius: 4px;
outline: 2px solid white;
outline-offset: -4px;
}
button:hover {
outline-color: transparent;
}
Example here: https://codepen.io/Happysk/pen/zeQzaZ

Resources