How to ignore element padding for ::before pseudo element? - html

Below is my solution for a pseudo element to ignore the padding, but it feels kind of "hacky" because I used negative margin on the pseudo element.
Is this solution is OK?
I also tried to use left: 0; top: 0;, but then I got my pseudo element positioned relative to the body of the page, not the element. Why?
CSS:
.block-header {
background-color: #3A658B;
height: 30px;
width: 100%;
line-height: 30px;
color: white;
font-size: 18px;
border-radius: 3px;
padding-left: 10px;
}
.block-header::before {
content: '';
position: absolute;
margin-left: -10px;
height: 30px;
width: 10px;
background-color: #1E3552;
border-radius: 3px 0px 0px 3px;
}

Using left: 0 is fine. That's the right method.
Except you haven't specified position: relative on the .block-header element.
Consider this:
A pseudo-element is considered a child of its DOM element.
An absolutely-positioned element is positioned relative to its nearest positioned ancestor.
When there is no positioned ancestor, the abspos element is positioned relative to the initial container (i.e., the HTML element / viewport).
.block-header {
background-color: #3A658B;
height: 30px;
line-height: 30px;
color: white;
font-size: 18px;
border-radius: 3px;
padding-left: 10px;
position: relative; /* NEW */
}
.block-header::before {
left: 0; /* NEW */
content: '';
position: absolute;
height: 30px;
width: 10px;
background-color: #1E3552;
border-radius: 3px 0px 0px 3px;
}
<div class="block-header">test</div>
See MDN for more information.

Related

Create Button with toggle and text with a single element

I'm trying to create a button out of a single html element. The button needs to have a toggle slider and the text needs to be aligned vertically and horizontally. So I thought I can make use of :before element to help me make that happen. Here is what I have tried:
div {
width: 140px;
height: 40px;
background-color: #B3B3B3;
color: #FFF;
float: left;
clear: both;
border-radius: 5px;
font-size: 12px;
}
div:before {
content: '';
display: block;
width: 20px;
height: 36px;
background-color: #4D4D4D;
position: relative;
left: 2px;
top: 2px;
float: left;
border-radius: 5px;
}
<div>Text Value</div>
I have 2 problems with the above code:
I can't position the text how I want and I have tried using text-align and position to move it around.
I am using a float, which means that it will affect behavior of other elements around it, and I really don't want that.
Is what I want possible with a single element?
Here is the JS Fiddle: https://jsfiddle.net/m3q5Lcjy/
EDIT: The centered text should not be centered on the whole element, but on the light gray area.
This is how I would do this:
Array.from(document.querySelectorAll('.toggler')).forEach((item) => {
item.addEventListener('click', e => {
item.classList.toggle('active');
})
});
.toggler {
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-sizing: border-box;
padding-left: 24px;
width: 140px;
min-height: 40px;
background-color: #B3B3B3;
color: #FFF;
border-radius: 5px;
font-size: 12px;
text-align: center;
cursor: pointer;
transition: padding .25s ease;
}
.toggler.active {
padding: 0 24px 0 0;
}
.toggler:before {
content: '';
display: block;
width: 20px;
background-color: #4D4D4D;
position: absolute;
bottom: 2px;
left: 2px;
top: 2px;
border-radius: 5px;
/* transition to make it look smoother */
transition: left .4s ease;
z-index: 1;
}
.toggler.active:before {
left: calc(100% - 22px);
}
<div class="toggler">Text Value</div>
<hr />
<div class="toggler active">Text Value realllllyy long</div>
<hr />
<div class="toggler">Text Value really far too long for this tiny, tiny, ohhh so tiny button. I recommend using shorter text though, but it won't break not even if you have like 10 or more lines.</div>
If anything about this implementation is unclear, feel free to ask.
Use flexbox to center your text vertically and horizontally. Then use absolute positioning on your pseudo element. Make sure parent element has relative positioning applied so absolute positioned pseudo stays within the parent.
div {
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-sizing: border-box;
padding-left: 24px; /* 20px for :before width, 4px for :before offset */
width: 140px;
height: 40px;
background-color: #B3B3B3;
color: #FFF;
border-radius: 5px;
font-size: 12px;
}
div:before {
content: '';
display: block;
width: 20px;
height: 36px;
background-color: #4D4D4D;
position: absolute;
left: 2px;
top: 2px;
border-radius: 5px;
}
<div>Text Value</div>
You could place the text in a paragraph.
<div class="thediv">
<p class="theText">
enter text here
</p>
</div>
.thediv{
Your own style.
}
.theText{
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
}
I don't see why you would want it be in one element.
If you do want that, you should give the div a padding.
div{
background-color: #B3B3B3;
color: #FFF;
float: left;
border-radius: 5px;
font-size: 12px;
padding: 20px 70px;
}

css border with triangle shape

Is there any way to create the border on the left with css ?
Here is a way to do it using CSS; you are just layering a Parallelogram and a Rectangle:
.espanolIcon
{
width: 300px;
height: 100px;
padding-left: 30px;
}
.rectangle {
position: absolute;
top: 0px;
left: 200px;
width: 200px;
height: 100px;
background-color: green;
border-radius: 0px 0px 30px 40px;
}
.arrow-left {
position: absolute;
top: 0px;
width: 300px;
height: 100px;
background-color: green;
-webkit-transform: skew(22deg);
transform: skew(22deg);
border-radius: 0px 0px 30px 40px;
}
h1 {
color: white;
}
<div class="espanolIcon">
<div class="rectangle"><h1>Espanol</h1></div>
<div class="arrow-left"></div>
</div>
Use a zero-dimension :before with thick, partial borders
By adjusting the top/bottom and left/right values of border-width on the :before pseudo-element, you can effectively change the skew of the triangle. The left position can then be changed to properly align the pseudo-element.
a {
display: inline-block;
position: relative;
margin-left: 14px; /* Should counter `left` value of `a:before` */
padding: .5em 1em;
color: #fff;
font: bold 1em/1 sans-serif;
text-decoration: none;
text-transform: uppercase;
border-radius: 0 0 10px 10px;
background: #75bf41;
}
a:before {
content: '\200B'; /* zero-width non-breaking space */
display: block;
position: absolute;
top: 0;
left: -14px; /* Adjust to align */
width: 0;
height: 0;
border-width: 14px 8px; /* Adjust top/bottom and left/right to skew */
border-style: solid;
border-color: #75bf41 #75bf41 transparent transparent; /* Triangle orientation. */
}
Español
Full css could work, but you should use .png as background-image or perhaps you could use .svg as you can animate and/or change every point or pixel. You might be able to use just CSSbut it would take a lot of leveling and positioning and alot of layers of absolute and relative positioning. As Css would only change the full width of the element, and it can only be used to change the width of elements. What you can do is use .svg, you could map every pixel which could be animated.
I accomplished it using borders and pseudo elements.
<ul>
<li class="lang-item lang-item-6 lang-item-es">
::before
<a>Español</a>
</li>
</ul>
ul {
position:relative;
}
.lang-item {
text-align: right;
position: relative;
}
.lang-item a {
background: #76c53f;
padding: 15px;
color: #fff;
text-transform: uppercase;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 14px;
}
.lang-item::before {
position: absolute;
right: 101px;
top: -15px;
content: "";
display: inline-block;
border-top: 40px solid #76C541;
border-left: 40px solid transparent;
}
jsfiddle

Z-index object center alignment

#sidebar input[type=text], input[type=password] {
margin-left: 13px;
height: 22px;
width: 129px;
border: none;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
background-color: #d9e4ea;
font-size: 13px;
position: relative;
z-index: 2;
}
input[type=submit] {
margin: 0;
width: 101px;
height: 16px;
background: url(images/img06.png) no-repeat left top;
border: none;
position: absolute;
z-index: 1;
cursor:pointer;
}
I have two input types and I want the submit button to be behind the text input and to be centered on the y axis respectively to the first object (text input). I can't manage to center it correctly. I can do it by adjusting margins but then I get different result in every browser and so it's not exactly in the center.
http://jsfiddle.net/7hbq5/10/
To vertically center an absolutely positioned element with known height inside it's parent container is an easy task and guaranteed to work cross browser:
.centeredVertically {
position: absolute;
height: 16px;
top: 50%; /* push down by 50% of the height of the container */
margin-top: -8px; /* bring it back up by half of it's height */
}
Make sure you add position: relative to your form so that it becomes the context for your submit button. See the fiddle:
http://jsfiddle.net/7hbq5/11/
I think you want align the divs on y axis. If you have width of the both input boxes predetermined, just use position absolute for both and give left and top on both the divs.
See the fiddle
http://jsfiddle.net/7hbq5/12/
input[type=password] {
height: 22px;
width: 129px;
border: none;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
background-color: rgba(0,0,0,0.4);
font-size: 13px;
position: absolute;
z-index: 2;
top:0;
left:0;
}
input[type=submit] {
position: absolute;
left:14px;
top:3px;
width: 101px;
height: 16px;
border: none;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
background-color: #ff672a;
position: absolute;
z-index: 1;
cursor:pointer;
}
put position relative on the parent div to start a new BFC. (the children are absolute wrt the div)

How implementation margin-bottom for position: absolute element

I don't know how in this case implementation margin-bottom for position: absolute element.
This is css of my element:
font-family: FuturaRoundBold;
display: none;
position: absolute;
left: 15%;
top: -5%;
color: #000;
width: 75%;
padding: 1%;
background-color: rgba(233, 233, 233, 1);
border-radius: 30px;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
-khtml-border-radius: 30px;
z-index: 2;
Thanks for any ideas!
margin-bottom will only do anything to an absolutely-positioned element if the element has no top property.
Remove the top: -5% and then your margin-bottom will work.
Or as mentioned in the comments you can also add a transparent div like this
<div class="spacer"></div>
inside your outside div
.spacer {
height: 50px;
margin: 0 0 -50px 0;
/* margin: 20px 0 -50px 0; use this if you want #container to have a 'bottom padding', in this case of 20px */
background: transparent; /* you'll need this if #container's parent element has a different background from #container itself */
}
courtesy : Joey

Position absolute not working on pseudo element in firefox 12+

I am having a problem with the positioning on a pseudo element in firefox 12+ (maybe earlier). The element looks as if relative to the page however I do have position:relative on the anchor tag. Any suggestions ?
HTML
Test File
CSS
a[rel~="attachment"] {
display: inline-block;
position: relative;
background: #EAE3EA;
height: 64px;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
-khtml-border-radius: 7px;
border: 3px solid #515151;
display: table-cell;
text-align: center;
vertical-align: middle;
padding: 0 5px 0 47px;
font-weight: 400;
}
a[rel~="attachment"]::before {
content: '';
background: url(img/file.png) no-repeat;
width: 37px;
height: 48px;
top: 5px;
left: 5px;
position: absolute;
}
Instead of using relative positioning you could use margins to position a::before keep in mind you can use negative margins so you have plenty of control over the element's positioning.
you overwrote
display: inline-block;
with
display: table-cell
maybe using display inline-block does the trick