Can I make a pure css tabbed border? - css

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.

Related

CSS ribbon-like header

I'm trying to get a ribbon-like banner effect for a header:
My markup is this:
<header>
<div id="logo">
<img src="">
</div>
</header>
I was thinking I could use pseudo :before and :after elements on the <img>, creating extra white space above and below the image to fake the extended `div:
#logo-wrap img:after {
content: '';
display: inline-block;
position: absolute;
left: 10px;
top: 10px;
width: 100px;
height: 100px;
background-color: #000;
}
And then another :before and :afterpseudo elements for the "shadow-fold".
My problem is: if I end up doing it like this, I'll have to insert another div between #logoand <img> in order to add another pair of :before and :after pseudo elements for the bottom "shadow-fold" and I think I'm having problems using the pseudo elements on the <img> element (nothing is appearing).
Can you shed some light and guide me on the right direction, pls? Perhaps, there is a simple way to just "shrink" the <header>?
EDIT
So, :before and :after can't be used with <img>. Thank you for the info :)
What I would like to know is if there is another way to achieve what I desire instead of wrap-wrap-wrap? :P
i.e: is there a way to make the #logo be bigger than <header> despite being its child and its height being the same (since the <header> has always the same height as the <img>)?
Thanks
I think you're on the right track. I would use borders, but I would make your pseudo-elements be behind the logo like so:
body,html {margin: 0; padding: 0;}
header {
background: #eee;
text-align: center;
margin: 1em 0;
}
#logo {
display: inline-block;
vertical-align: top;
position: relative;
margin: -0.5em 0;
}
#logo:before, #logo:after {
content: '';
position: absolute;
width: 100%;
left: -0.25em;
border: 0 solid transparent;
border-width: 0.5em 0.25em;
color: #aaa; /* set so we only have to have the border color in one place.
if not specified, border color is the same as the text
color. */
}
#logo:before {
border-top: none;
border-bottom-color: initial;
top: 0;
}
#logo:after {
border-bottom: none;
border-top-color: initial;
bottom: 0;
}
#logo img {
position: relative;
display:block;
z-index: 1;
}
<header>
<div id="logo">
<img src="//placehold.it/300x100?text=LOGO"/>
</div>
</header>
The concept is that the pseudo-elements are 100% width of the logo with a little bit extra (determined by the border attributes). Then you use both left and right borders simultaneously. There's a few other tricks in that code that help simplify it, but the general idea is to let your pseudo-elements peek out from behind the logo itself.

Layout of pseudoelements inside a button in Opera

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.)

Why doesn't inset box-shadow work over images?

I have a container that uses inset box shadow. The container contains images and text. The inset shadow apparently does not work on images:
The white section here is the container. It contains a white image, and there is inset box shadow applied to it.
body {
background-color: #000000;
}
main {
position: absolute;
bottom: 0;
right: 0;
width: 90%;
height: 90%;
background-color: #FFFFFF;
box-shadow: inset 3px 3px 10px 0 #000000;
}
<main>
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Solid_white.png">
</main>
Is there a way to make the inset box shadow overlap images?
Just to chime in on this, because I was just creating something similar...
I hate polluting my markup with extra elements for the sake of styling, so the CSS solution is to use the :after pseudo element:
main::after {
box-shadow: inset 3px 3px 10px 0 #000000;
content: '';
display: block;
height: 100%;
position: absolute;
top: 0;
width: 100%;
}
<main>
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Solid_white.png">
</main>
It's probably too late for what you were trying to do, but is the better solution in my estimation.
Because the shadow is part of the parent container it renders below the image. One alternative is to have a div which places a shadow overtop the image like so:
body {
background-color: #BBB;
}
main {
position: absolute;
bottom: 0;
right: 0;
width: 90%;
height: 90%;
background-color: #FFFFFF;
border-radius: 20px;
}
main img {
border-radius: 20px;
}
.shadow {
position: absolute;
width: 100%;
height: 100%;
box-shadow: inset 3px 3px 10px 0 #000000;
border-radius: 20px;
top: 0;
left: 0;
}
<main>
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Solid_white.png" />
<div class="shadow"></div>
</main>
Edit: I've updated the fiddle to include border radius on the shadow and on the img which solves the issue identified in the comments.
The reason it's not overlapping is because the image is inside the div, so the image is on top of it. The image is higher (closer to the user) than the div.
You can change the image to use position: relative; z-index: -1, and have the containing div use a border instead of setting background color on the body. You'll need to use box-sizing: border-box to include the border in the width of the div.
DEMO
body {
background-color: #FFF;
}
main {
position: absolute;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
border: 60px solid black;
box-shadow: inset 3px 3px 10px 0 #000000;
box-sizing: border-box;
}
img {
z-index:-1;
position: relative;
}
For those, who're using absolute-positioned, full-size :before/:after pseudo elements, consider using pointer-events: none on the pseudo-element so the original elements remain clickable.
The best way to achieve this in 2020 would be to use mix blend mode on the image. use the box-shadow on the parent element of the img and use mix-blend-mode: multiply.
You could set the image as the div's background instead:
background-image:url(http://www.placehold.it/500x500)
jsFiddle example
https://stackoverflow.com/a/21415060/6235358
that's a great way to do it but we can do it in a better way using the ::after pseudo-class so you'll not have to add an empty <div> to your HTML
As Rilus mentioned we could use a pseudo class. Unfortunately this does not seem to work on an img tag for some reason however we can use a combination of inner and outer containers to achieve the affect we need.
.outer:hover .inner:after {
position: absolute;
content: '';
color: white;
display:block;
bottom: -0px;
right: -0px;
width: 100%;
height: 100%;
z-index: 11;
border: solid 10px red;
}
http://jsbin.com/kabiwidego/1/
not sure about ie 10 though as it seems to handle pseudo classes that are absolutely positioned slightly differently to most browsers.
One simple fix if you are clever with your decimals is to store your content in a separate div which you then select and implement a certain number of pixels from the top.
For example, let's say your header has a height of 50px. You could begin your #content div id 53.45px from the top (or whatever height your drop shadow is) and then your shadow would appear above the images.
One issue with this is that if you are using a rather transparent shadow, the more transarent it is the more tacky it may look by implementing this css.
In practice the code would be as follows:
HTML:
<header>
Whatever's in your header
</header>
<div id="content>
Page content
</div>
CSS:
header {
height: 50px;
box-shadow: 0 5px 5px rgba(0,0,0,1);
}
#content {
top: 55px;
}
Even if i'm late for the party, I had the same issue these days and worked on a solution. For me, the best solution (mobile friendly) is this one:
JSFiddle:
.image-inset-container {
margin-bottom: 30px;
}
.image-inset-shadow {
position: relative;
}
.image-inset-shadow img {
border-radius: 20px;
}
.image-shadow {
position: absolute;
width: 100%;
height: 100%;
box-shadow: inset 3px 3px 10px 0 #000;
border-radius: 20px;
top: 0;
left: 0;
}
<body>
<h4>Reimagined Web Design</h4>
<p>With your input and business goals in mind, we bring your brand to life through custom human-facing graphics and
visual elements targeted toward your audience for good user experience and created in future-forward technology,
guaranteeing a successful new web design.</p>
<div class="image-inset-container">
<div class="image-inset-shadow"><img src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Solid_white.png" alt="img1" />
<div class="image-shadow"></div>
</div>
</div>
<p>We initiate a collaborative process where your team is involved in every step to create a frictionless and
delightful
experience for your customers. Our designers immerse themselves in your industry and your brand aesthetic to
deliver
a website that represents your business while achieving your goals for a connected future.</p>
</body>

PNG shadow with fluid height

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

:after pseudoelement is cropped when using filter in IE8

This is the HTML:
<div id="target"></div>
CSS:
#target {
position: relative;
width: 200px;
height: 200px;
background: #F00;
-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#F00,endColorstr=#F00)";
}
#target:before {
content: "content from before";
position: absolute;
top: 10%;
left: 10%;
width: 100%;
height: 100%;
background: cyan;
}
here is the jsfiddle:
http://jsfiddle.net/8BzW6/
If you comment the filter then the "after" element is not cropped by the parent element (#target).
Do you know how to solve this?
(I need a gradient and I don't want to use an image)
Using Microsoft's filter for me is a bad practices, it will always cause issues. And if you combine it with modern technics like CSS3 its getting even worse.
What about using inline 1px gradient image using data64?
Here is a generator: http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/

Resources