Transparency on background influence the text - css

On my website, I have a slider with some text placed upon it. I've given the text a black, transparant background, so it would be a bit more readable.
As you can see, it's exactly the effect I'm trying to achieve. But for some reason, my CSS does influence the text too with it's opacity filter...
The text isn't 100% white anymore. Is there a way to overrule this kind of CSS behavior?
EDIT: IE8 should be supported...
This is my CSS:
.front-slider-body {
background-color: #000;
zoom: 1;
filter: alpha(opacity=50);
opacity: 0.5;
}

Thats because the whole elements opacity has been changed, not just the background.
If you want just the background-color to be opaque then change the opacity of that property by using rgba instead of a hex code:
background-color: rgba(0,0,0, 0.5);
Full class:
.front-slider-body {
background-color: rgba(0,0,0, 0.5);
zoom: 1;
}
The following shows a list of browsers which this is supported in:
http://caniuse.com/#search=rgba
If you need to support older browsers, then I would recommend creating a 1px*1px semi-transparent image and use that as a background-image. It's not tidy, but its a solution for old browsers.

instead of
background-color: #000;
filter: alpha(opacity=50);
opacity: 0.5;
use
background-color: rgba(0,0,0, .5);
rgba() is available on IE>8 and will affect the background only, leaving text and nested elements with full opacity

Modern browsers (IE9+, FF, Chrome)
Provide transparency just for your background and not the whole element (as others have pointed out) by using
background-color: rgba(0, 0, 0, .5);
Older browsers (including IE7+)
Older browsers(of the Microsoft kind) don't support rgba so in this case you can use PNG with alpha channel to achieve the same result (and would also work in modern browsers):
background-image: url(transBack.png);
Your PNG should be coloured black with 50% transparency.

You might want to try separating the background from the text. The text inherits the opacity of it's parent, which is the problem you're facing. To fix this, set the background as a sibling of the text. So, instead of:
// Just example layout
<div id="container" style="background: #000; opacity: 0.5;">
Your Text
</div>
You might try:
<div id="container" style="position: relative;">
<div id="background" style="position: absolute; width: 100%; height: 100%; background: #000; opacity: 0.5;" ></div>
<div id="text">Your Text</div>
</div>
(obviously, you'd use classes and more cross-browser compliant CSS - this is just to demonstrate the concept)

Related

How can I make a single run-of-text outlined in some areas and a solid-fill in other areas?

I recently came across this dribbble/landing page concept with hollow/filled text.
First off I'm not entirely sure if this concept could be recreated in CSS.
A bit of Google did lead me to CSS text masks, but I wasn't able to find any post that can really recreate this effect.
How would I be able to reconstruct the hollow/filled text, depending if the background behind the text has an image or not?
It can be done in pure-HTML+CSS (without any SVG).
And it can be done in pure SVG too.
The SVG-only option will be simpler because SVG has more powerful blending and masking capabilities that aren't (yet) able to be used by HTML elements (CSS boxes).
I decided to do it for HTML+CSS because I felt like a challenge.
This HTML version is animated and the text is fully selectable.
This HTML+CSS version can be simplified further by using mask-image: element(#target) which means we don't need the mask-only text, unfortunately Chrome doesn't seem to support element() yet (but Firefox does, though).
A minor wart is the text-stroke outline does not exactly line-up with the solid white text (at least in Chrome on Windows 10 with my computer's version of Helvetica at 96dpi, but at 192dpi (2x, aka Retina)) in the same browser and computer it looks perfect.
Here's how it looks at different points in the animation on my machine at 96dpi:
The example implementation below works in the following browsers (at the time of writing):
Chrome 98
Edge 98
Firefox 97
macOS Safari Technology Preview (Release 137)
It kinda works in macOS Safari 15.2, but you have to click on it first for some reason.
It doesn't work in iOS Safari 15.1 (only the outlined text is visible, the solid text doesn't render at all).
Because it does work in the Safari Preview browser it should work in the next update to iOS Safari and macOS Safari, however.
body {
background-color: #dbdac2;
--solid-white: linear-gradient(white,white);
}
#container,
#container > #div1 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-size:
153px 302px,
148px 302px,
154px 302px;
background-position:
131px 94px,
309px 28px,
480px 94px;
background-repeat:
no-repeat,
no-repeat,
no-repeat;
animation: moveImages 2s infinite;
animation-direction: alternate;
}
#container {
border: 1px solid white;
position: relative;
width: 711px;
height: 440px;
/* These are the 3 photo images, rendered as separate background-image layers: */
background-image:
url( "https://i.stack.imgur.com/hmwyh.png" ),
url( "https://i.stack.imgur.com/JeHEg.png" ),
url( "https://i.stack.imgur.com/pVgz6.png" );
}
#container p {
margin: 0;
position: static;
padding-top: 192px;
padding-left: 62px;
overflow: hidden;
font-family: Helvetica;
font-size: 99px;
letter-spacing: -2px;
font-weight: 600;
}
#container > #pStroke {
text-stroke: 1px white;
-webkit-text-stroke: 1px white;
color: transparent;
}
#container > #div1 {
/* #div1's background-image layers must match #container's: */
background-image:
var(--solid-white),
var(--solid-white),
var(--solid-white);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
#keyframes moveImages {
/* The `#keyframes from {}` rule is optional, btw. */
to {
background-size:
53px 302px,
58px 302px,
154px 302px;
background-position:
431px 94px,
209px 28px,
280px 194px;
}
}
<div id="container">
<div id="div1">
<p id="pWhite">Fashion Give<br />Impression.</p>
</div>
<p id="pStroke">Fashion Give<br />Impression.</p>
</div>
Explanation:
The div#container element has a background-image property set to 3 different sources images (using meme images in lieu of the fashion photos from your posted example).
These images can be positioned and scaled independently via the background-size and background-position properties.
Another element (#div1) overlays div#container through absolute positioning and has the same background-size and background-position properties, but uses a single solid white background image (from a linear-gradient(white,white)) instead of the photos, and then those 3 white background image layers are masked by #div1's inner <p>'s text using background-clip: text;.
This example has to use background-image: linear-gradient (or background-image: url("1x1px-white.png");) instead of background-color: white; because it needs to be repeated in 3 separate layers, whereas background-color: white; cannot be used to define a rectangular area within the background, nor can you have multiple background-color layers (even when semi-transparent).
The example also has to use DOM text to mask the white rectangles - instead of using white rectangles to mask the DOM text - because CSS-in-HTML doesn't support any kind of reversed text masking though, otherwise this would be a lot easier. I believe this is easily possible in SVG, however.
#div1's <p> element is used to position the text correctly by using only its inner padding instead of position: absolute; because positioned text cannot be used with background-clip: text;, unfortunately.
Another <p> element with a copy of the text is used for the stroked text (with text-stroke: 1px white;)
While the text content is duplicated in the HTML source, the more fiddly size and position information of the 3 images (and their respective white masks) does not need to be duplicated in the CSS, fortunately; thanks to how CSS's selectors work (as both #container and #div1 have their background-size and background-position properties set by a single CSS rule).
Possible alternative approaches:
Instead of using a repeated identically sized background-image layers for the solid white parts, a single (but horribly complicated) clip-path tracing the 3 boxes (like a single line drawn like an etch-a-sketch) could be used on #pWhite but this would not be feasibly animatable.
I think the best possible approach would be something like this:
Using 3 separate <img /> elements for the 3 photos (instead of background-image) and using absolute positioning inside a new <div id="images">.
And then the solid white text <p> (in a sibling element to div#images) would be absolute-ly positioned over div#images by z-index and masked with mask-image: element(#images);
But Chrome doesn't seem to support using element() in HTML+CSS, only Firefox does, as far as I know.
The stroked text would remain as a duplicate <p> element positioned behind the div#images.
Another advantage of this approach is that the <img/> elements can be positioned using transform: translate instead of having to go through background-position or position: absolute which would yield much better performance and framerates.
I can't think of any approaches that don't require duplicating the text content, though - at least until CSS's content: property allows elements to copying text from other elements.

How do I recreate a web form like this without reducing the opacity of form elements?

I want to create a form similar to this on my website. Unfortunately, when I lower the opacity of the div conaining my form elements, the e-mail, password, and text all reduce in opacity as well. How can I make a form like this where only the surrounding box is see-through, but my login elements, title, and buttons are not?
Create a div with background:rgba( 255, 255, 255, 0.3 ); and than simply add the inputs which than could look somehow like this:
.login_wrapper {
width:300px;
height:375px;
background: rgba( 255, 255, 255, 0.3 );
margin:0 auto;
}
.login_wrapper h1 {
padding-top:30px;
text-align:center;
color:#fff;
}
.login_wrapper input[type=text] {
width:80%;
height: 25px;
margin-left: 10%;
margin-top: 10px;
}
body {
height: 100%;
width: 100%;
background:url("https://unsplash.imgix.net/photo-1428591501234-1ffcb0d6871f?dpr=2&fit=crop&fm=jpg&q=75&w=1050");
background-size:cover;
}
<div class="login_wrapper">
<h1>Create Account</h1>
<input type="text"/>
<input type="text"/>
<input type="text"/>
</div>
I think you now get the idea.
You can set the opacity of the background div using rgba. For example:
.form-container { background: rgba(0, 0, 0, 0.5); }
The last parameter for rgba is the alpha value and controls the transparency of the background.
The surrounding box is not actually "see through" - you'll notice it actually contains a blurred version of the page's background image in addition to a lightened effect.
I feel the best way to achieve this, at the cost of dev-time, is to create two background images (the page's background, and a blurred, lightened version of the same in Photoshop) and set the background-image of the elements accordingly. You can use CSS's new calc function to help keep the images aligned if you're doing any advanced trickery.
The simpler approach, though considerably more CPU intensive on the web-browser and not supported by browsers older than a few years is to use CSS's blur filter. This is documented here: How to apply a CSS 3 blur filter to a background image
The way I've always done this has been...
<div class="overlay">
<div class="overlay-content">
<h2>Whatever</h2>
<form><!-- foo --></form>
</div>
</div>
.overlay-content has a bg color (white to lighten, black to darken) such as background-color: rgba(0,0,0,0.3); with a transparency value.

CSS: Opacity Issue

Ok, so in my page I am showing a background image with this css:
.heroarea {
background:url(/static/images/mrd_hero_01.jpg) no-repeat;
height:450px;
}
and the copy placed over it and the container the copy is in have these styles:
.main-panel {
position: absolute;
top: 130px;
left: 380px;
background: #fff;
width: 560px;
height: 340px;
padding: 30px 30px 20px 30px;
/* CSS3 standard */
opacity:0.5;
/* for IE */
filter:alpha(opacity=50);
}
.main-panel h1 {
background: transparent;
color:#39372f;
text-align: center;
/* CSS3 standard */
opacity:1;
/* for IE */
filter:alpha(opacity=100);
}
Generally, everything is as expected. That is, the image shows where I expect it to show. main-panel shows a white back ground with a transparent background. However, the text in the h1 tag is also transparent. I can see the image from underneath showing through. How can I make this so that the h1 tag content is not opaque?
Thanks!
Opacity applies to the element, not it's background.
You either need to use a translucent image, or an rgba background colour.
There is an explanation about how to do this in a backwards compatible way. (Disclosure: My site)
Use rgba and/or transparent png. Alternatively, move the content to a separate sibling div as the background:
<div id="parent">
<div id="opacity"></div>
<div id="child">text</div>
</div>
If you use transparency on a block element it makes the child element inside transparent as well.This is how css works ! I do not think there is any way to hack out of it. What you can do it to absolutely position h1 without making it a child or use a translucent image
It looks like your text is a child of .main-panel. It will take on 50% opacity. Even though you state the text is opacity 100% will only make it 100% of 50%. You will need to layer it outside of .main-panel and place it on top.
You have to move it outside of its .main-panel parent. There's no way to override the 50% opacity that's being applied there.
Alternatively, if you're only using 50% opacity to make the mrd_hero_01.jpg background image transparent, you could convert it to a .png with 50% opacity and then you wouldn't need to set the opacity on .main-panel.

Is Opacity is INHERITED in a div

Is it possible to remove the opacity inheritance from a parent to it's child div?
Example
<style type="text/css">
.parent {
opacity:.5;
}
.parent div {
opacity:1; /* I want this to override the ".5", but instead it combines */
}
</style>
<div class="parent"><div></div></div>
Like fmsf says, it's not possible.
If you're looking for a way to make background-color or color transparent, you could try rgba. This is not supported in IE6.
#my_element {
/* ie6 fallback - no opacity */
background-color:rgb(255, 255, 255);
/* rgba(red, green, blue, alpha); */
background-color:rgba(255,255,255,0.5);
}
No, not strictly in the sense you're inquiring about. Because what's happening is not really that the value is inherited in any traditional sense, but the child control is part transparent as a direct effect of being within a partly transparent container.
You can work around it, tho, in a lot of situations.
So this won't work:
<div id="parent" style="opacity: 0.5; background-color: red;">
<div id="child" style="opacity: 1"> Still just 50% visible </div>
</div>
But you could do something like this:
<div id="wrapper" style="position: relative;">
<div id="parent" style="position: absolute; top: 0; left: 0; opacity: 0.5; background-color: red; width: 100%;"> </div>
<div id="child" style="position: absolute; top: 0; left: 0;"> This will be 100% visible </div>
</div>
There are a handful of caveats, but this is the only good way to achieve what you want.
In this example I'm dealing with one line of text, and in the "parent" I'm including an which will also occupy one line in height. If your "child" is of a greater height, the "parent" will not grow, because it is really not a parent at all. You'll have to manually set a height.
You'll also manually have to specify width, as you're dealing with absolutely positioned elements.
I'll say, tho, before people start saying that absolute positioning is such a terrible way to solve design problems, that there is one occasion where I think it is perfectly legit: when also dealing with position: relative as in the above example, and to absolutely position an element based on that, and not on the entire window.
No you can't
Opacity is completly inherited from the fathers div.
meaning:
#father{
opacity: 0.5;
}
#child{
opacity: 0.9; /* actualy means opacity 0.5*0.9 == 0.45 of opacity value */
}
Edit:
If you want to cheat it but retaining the "workflow" of your transparent father. You can put a copy (in size and position) of the father div, on top of the father.
#father, #copy{
your css here
opacity: 0.5;
}
#copy{
opacity: 1;
background: transparent;
z-index: 1000; /* or one more than the father */
}
Now instead of putting your non transparent HTML on the father, put it on the copy.
Create a transparent PNG and apply it as the background of the parent class instead of using opacity.
For a demo, see Twitter's layout (specifically the background/border around the main content).
You can avoid the parent-child opacity inheritance but it will be hacky:
http://www.impressivewebs.com/css-opacity-that-doesnt-affect-child-elements/
There is also a plugin to do the job, called: thatsNotYoChild.js.
With HTML5 you can also use RGBA to set a background color whose transparency (alpha) is not inherited.
Example:
/* Black with 75% transparency */
background-color: rgba(0, 0, 0, 0.25);

Transparent div problem

Hey i have this div that shows as a popup:
<div class="popup">
</div>
Then with jquery i add another class to it to give it with the css associated to that class, position, size, color and transparency:
.show {
position: absolute;
color: #F4F5F6;
width: 600px;
margin-left: -300px;
height:300px;
background: #000000;
left:50%;
top:200px;
filter:alpha(opacity=95);
-moz-opacity: 0.95;
opacity: 0.95;
}
My problem is this:
I'm adding text and image to the div.
ending up like:
<div class="popup show">
<div class="image">
<img scr="blabla.png">
</div>
<div class="text">
ble ble ble
</div>
</div>
My problem is the following, even though i have overriden the opacity here:
div.image
{
position: relative;
float:left;
width:202;
height:402;
filter:alpha(opacity=100);
-moz-opacity: 1;
opacity: 1;
}
The image still apears with transparency.
Is there anyway to override the opacity values without having to put the image div outside of the popup div?
Since the '.show' class has an opacity of 95%, so will all of its descendants. It's unfortunate, but that's how opacity works. The descendants cannot overcome their ancestor's opacity as long as they still truly remain descendants.
You'll have to either set the '.show' background with a semi-transparent png or result to some awkward html (see: Non-Transparent Elements Inside Transparent Elements)
Not trying to be jerky, but this Google search (or something similar) might help
Try this:
div.image
{
position: relative;
float:left;
width:202;
height:402;
filter:alpha(opacity=100) !important;
-moz-opacity: 1 !important;
opacity: 1 !important;
}
http://www.w3.org/TR/CSS2/cascade.html#important-rules
EDIT: sorry; I've even come across this before and didn't twig. I think that the nested element's maximum opacity is the same as the outer element's opacity; you can never get more opaque than your parent element! Last I checked this is a proper CSS issue, and I don't know a workaround.
As a workaround, you could try not making nested, but use some ucnning positioning trickery.

Resources