I'm trying to use the :before and :after pseudoelements to add an icon to <button/> element. While it works fine for Chrome/Firefox/IE it breaks on Opera because its layout mechanism seems to be different. After some testing, I reduced it down to the following test case:
<style>
.foo {
display: block;
position: relative;
background: cyan;
width: 100px;
height: 100px;
padding: 0;
margin: 0;
border: 1px solid black;
}
.foo:after {
background: lime;
border: 10px solid yellow;
content: " ";
position: absolute;
left: 25px;
top: 25px;
width: 50px;
height: 50px;
}
</style>
<div class="foo"> </div>
<button class="foo"> </button>
Here, two different elements are styled with the same class. One would expect them to show approximately the same layout (and indeed it is the case in non-Opera browsers), but on Opera the layouts are drastically different:
This was tested using Chrome 33.0 and Opera 12.16 on Windows 7. It doesn't affect other subelements though, only the pseudoelements.
Is there a way to mitigate this problem without using "real" subelements?
(I should note that even after making the two elements have completely identical computed styles in Dragonfly, the problem still occurs.)
Related
I utilize the mix-blend-mode property on my portfolio site to achieve a fun effect with the landing page headline. I am using the multiply value to blend 3 layers that are cyan, magenta, and yellow. Where they overlap I would expect the result to be black.
That used to be the case. I've noticed recently, depending on the browser and display I view it on, that is not the case.
I put together a simple code pen to demonstrate this.
HTML
<main class="wrap">
<div class="color-wrap">
<div class="c"></div>
<div class="m"></div>
<div class="y"></div>
</div>
</main>
CSS
.wrap {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
}
.color-wrap {
width: 300px;
height: 300px;
border: 1px solid #000;
position: relative;
background-blend-mode: multiply;
}
.c, .y, .m {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
mix-blend-mode: multiply;
}
.c {
background-color: cyan;
top: 100px;
left:100px;
}
.m {
background-color: magenta;
top: -100px;
left:-100px;
}
.y {
background-color: yellow;
}
With Chrome and Safari, on my MacBook Pro display, the result of the 3 blended colors is a muddy purple. If I view it on my external monitor the result is closer to black. On Firefox, regardless of the display, the result is pure black. I'm attaching screenshots.
I don't like the muddy purplish color that I see in certain cases and wish this was more consistent. Any thoughts or insights?
MacBook Air display, Chrome Browser
External monitor, Chrome Browser
MacBook Air display, Firefox Browser
Before moving to my question, I know how the :before and :after selectors work. (not a duplicate of what is ::before or ::after expression). My question is in regards to use.
I've seen some inconsistencies over the years where these selectors have been used to display the same thing. Same results, different approach. In some specific cases, such as adding a font awesome icon within an li before the a the :before selector makes sense. I'm not inquiring about that use, since it's intuitive enough to understand. But take a speech bubble for a tooltip for instance. I have seen the triangle placed with a :before and also with an :after and in some occasions they use both! I'm confused.
What is the determining factor on choosing which selector should be used to attach an element such as the triangle on a speech bubble?
Allow me to demonstrate:
HTML
<div class="container">
<div class="bubble">This is my text in a bubble using :after</div>
<div class="bubble2">This is my text in a bubble using :before</div>
</div>
CSS
.bubble{
position: relative;
padding: 15px;
margin: 1em 0 3em;
color: #000;
background: #f3961c;
border-radius: 10px;
background: linear-gradient(top, #f9d835, #f3961c);
}
.bubble:after {
content: "";
display: block;
position: absolute;
bottom: -15px;
left: 50px;
width: 0;
border-width: 15px 15px 0;
border-style: solid;
border-color: #f3961c transparent;
}
.bubble2 {
position: relative;
padding: 15px;
margin: 1em 0 3em;
color: #000;
background: #f3961c;
border-radius: 10px;
background: linear-gradient(top, #f9d835, #f3961c);
}
.bubble2:before {
content: "";
display: block;
position: absolute;
bottom: -15px;
left: 50px;
width: 0;
border-width: 15px 15px 0;
border-style: solid;
border-color: #f3961c transparent;
}
IMG
Please don't tell me it's just a matter of preference. lol
DEMO
The naming of ::before and ::after is not entirely arbitrary, but it only really makes sense when the content of those pseudo elements is displayed inline, just before or just after the content of the element they are attached to.
As soon as you use
position: absolute;
in a pseudo element (which is totally legitimate), it no longer matters whether that pseudo element is named ::before or ::after.
It might just as easily be named ::presentational-frill-1 or ::presentational-frill-2.
Due to browser performance implications I can't use box-shadow CSS property because I have many similarly looking elements on my page that should have same looking style including shadow. That's the reason I would like to implement shadows using traditional PNG imagery.
Facts
My elements have predefined and more importantly fixed pixel width
They have fluid height (auto) depending on their content
They have content directly in the element and some child elements will be positioned outside their border
CSS3 can be used but performance-critical parts (gradients, shadows...) should be avoided
CSS pseudo elements can be used without limitation
Requirements
There should be no additional wrapper element added in order to have fluid shadow
Application should run smoothly on mobile browsers - shadows seem to slow down performance significantly on mobile devices since their processing power is much lower than desktop computers.
Possible direction
I thought of using :before and :after pseudos to display top-to-bottom and bottom shadows on the containing element, but these pseudos display within their parent element and positioning parent z-index higher than these children has no effect.
Visual demo of end result
This JSFiddle Demo in pure CSS3 that I would like to achieve but using PNG shadows. In reality there are numerous of these boxes so you can imagine mobile browsers are struggling with all these shadows.
Item is one such box (see blow) that needs PNG shadow. Left menu is child element positioned outside of the box.
Display in Chrome
HTML
<div class="item">
<menu>
<li>Yes</li>
<li>No</li>
<li>Maybe</li>
</menu>
<div class="content">
Some content
</div>
</div>
CSS3 LESS
.item {
position: relative;
width: 300px;
background-color: #fff;
box-shadow: 0 0 10px #ccc;
margin: 20px 20px 20px calc(20px + 3.5em);
min-height: 5em;
&:first-child {
margin-top: 0;
}
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 10px;
height: 5em;
background-color: #fff;
}
menu {
position: absolute;
top: 0;
left: -3.5em;
width: 3.5em;
margin: 0;
border: 0;
padding: 0;
list-style: none;
background-color: #fff;
box-shadow: 0 0 10px #ccc;
li a {
display: block;
text-align: center;
padding: 2px 0;
}
}
.content {
padding: .75em 1em;
}
}
Probably I am missing something, but looks like you want something in this way:
demo
The CSS is
.base {
width: 300px;
height: 150px;
font-size: 100px;
font-weight: bolder;
background-color: lightgreen;
position: relative;
z-index: auto;
}
.base:after {
content: '';
position: absolute;
top: 30px;
left: 30px;
background-color: green;
z-index: -1;
width: 100%;
height: 100%;
}
.child {
position: absolute;
left: 150px;
top: 50px;
border: solid 1px black;
color: red;
}
And just change the background of the :after to your image.
I have applied this solution to your fiddle.
The relevant CSS is for the before pseudo element:
.item:before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
z-index: -1;
background-image: url(http://placekitten.com/100/100);
background-repeat: no-repeat;
background-size: 100% 100%;
}
I have used a kitten picture, that is being scaled to cover all the needed size. Just change that to whatever you want.
I needed to do it that way because I had onky a pseudo element available.
The key for that to work (and where you probably had the difficulty) is to add z-index: auto to .item
Updated demo
Well, I had said that it wasn't posible, but I have find a way.
The standard technique would be to use 2 elements, just to avoid stretching the image (as you said). The problem is that we only have 1 pseudo element available.
The solution then would be to use 1 pseudo element, but with 2 backgrounds, to solve the issue.
CSS (only relevant part)
.item:before {
background-image: url(http://placekitten.com/320/10), url(http://placekitten.com/320/500);
background-repeat: no-repeat;
background-size: 100% 9px, 100% calc(100% - 9px);
background-position: left bottom, left top;
}
We will need an image (the first one) only 10 px in height, to cover the bottom shadow. And another one, with enough height to cover the maximumitem posible, and that will be used for the remaining part of the shadow. The dark part is that we need now a calc() height, with limited support. (anyway, better than border image)
demo 3
I want to give an element a border-top with a tab at the right corner like this:
Since this will be a repeated element within an Adobe Business Catalyst template, I want it to be pure CSS or at least CSS and javascript, without the use of any images. Is there any way this can be done?
Since it's just a decorative element, it doesn't have to be cross-browser.
Have a look at this:
http://jsfiddle.net/8hB7E/
HTML:
<body>
<div class="element">
</div>
</body>
CSS:
body { background: #555 }
.element { background: #000; border-top: 2px solid #fff; height: 100px; position: relative; width: 300px; }
.element:after { background: #fff; content: " "; height: 10px; position: absolute; right: 0; top: 0; width: 20px; }
It utilises the :after pseudo-element (which I find to be really useful!)
For more info see here:
http://coding.smashingmagazine.com/2011/07/13/learning-to-use-the-before-and-after-pseudo-elements-in-css/
Unfortunately this won't work in IE7 or 6 - it's not core to the functionality of the website though, so I'd say it's ok as is.
I have a few images generated dynamicaly :
<div class="image">
<?php echo "<img class='logo_client' src='img/clients/".$row['logo_name'].".jpg''>"; ?>
</div>
And I would like them to have rounded corner so that in my CSS I put :
.image {
padding: 0;
width: 100px;
height: 100px;
overflow: hidden;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
behavior: url(css/PIE.php);
}
I can see the rounded corners in Firefox, Chrome and IE9 but it's not working in IE8. The PIE thing is already working with other elements in IE8.
Does anyone know what it could be ?
Thank you very much
The only way I know of making rounded corners work in IE8 and below is with code like this:
<div class="image">
<span class="tl"></span>
<span class="tr"></span>
<span class="br"></span>
<span class="bl"></span>
</div>
and then with CSS like this:
.image { position: relative; }
.tl, .tr, .br, .bl { position: absolute; }
.tl { left: 0; top: 0; width: 20px; height: 20px; background: url(/images/tl.png) no-repeat top left; }
.tr { right: 0; top: 0; width: 20px; height: 20px; background: url(/images/tr.png) no-repeat top left; }
.br { right: 0; bottom: 0; width: 20px; height: 20px; background: url(/images/br.png) no-repeat top left; }
.bl { left: 0; bottom: 0; width: 20px; height: 20px; background: url(/images/bl.png) no-repeat top left; }
where the background images are all images of rounded corners corresponding to that corner, e.g. the bottom right hand corner background image might look like this:
and so one (hope that makes sense)
There might be nicer ways to do this, as the above method is a bit laborious, and not particularly clean.
Saying that, I doubt any ways of getting rounded corners to work in IE8 and below will be particularly "clean". I usually just leave IE8 and below without rounded corners, not that many people even use 7 and 8 anymore in comparison to other browsers.
EDIT:
If I were you I'd steer well clear of code like this "behavior: url(css/PIE.php);" IE behaviours are not supported in other browsers, I think even Microsoft gave up on them.
Finaly I made it work with CSS3 PIE. Rounded corners appear appear in IE7, IE8 and all other browsers. It was a coding mistake, sorry.