I have a container div I'm using to create a speech bubble pointing to the right like this:
.container {
width: 90%;
height: auto;
padding: 10px;
position: relative;
border-radius: .4em;
}
.container:after {
content: '';
position: absolute;
right: 0;
top: 50%;
width: 0;
height: 0;
border: 0.813em solid transparent;
border-left-color: #ffffff;
border-right: 0;
border-top: 0;
margin-top: -0.406em;
margin-right: -0.812em;
}
When the screen is smaller than 700px, I need the following CSS to apply instead, which creates a pointer facing down instead of right:
.container:after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
border: 0.813em solid transparent;
border-top-color: #ffffff;
border-bottom: 0;
border-right: 0;
margin-left: -0.406em;
margin-bottom: -0.812em;
}
This is how I'm trying to accomplish this, but the speech bubble doesn't seem to react.
#media(max-width:700px) {
.container:after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
border: 0.813em solid transparent;
border-top-color: #ffffff;
border-bottom: 0;
border-right: 0;
margin-left: -0.406em;
margin-bottom: -0.812em;
}
}
If I apply that code directly to .container:after outside of the media query it displays perfectly, but I can't seem to use media query to switch between the two types of speech bubbles. I'm guessing this is a syntax error, do I need to target the div ID instead of the class? The ID is chat_bubble, and here's a code pen.
https://codepen.io/TheNomadicAspie/pen/JjWVbKJ
Your media query is working just fine, the "problem" with your code is that your default styling (Outside of media query) is also applying to the part that's within media query, so under 700px viewport, your :after element has both top: 50%, as well as bottom: 0 properties, same goes for left and right properties, which is why you don't get to see your speech bubble triangle, you can fix this by setting top and right properties to unset for example. otherwise, another solution is to create another media query that will apply 700 pixels and upwards and have your default pseudo element styling
`#media(min-width:700px) {
...
}`
so that your element properties don't "overlap" each other.
Related
Currently I have this html in pug and vue code which is working fine. Basically the arrow width is dynamic.
.abc--step-bar: .abc--step-bar-color(:style="`width: ${progressBar.width}`")
.row
.col(v-for="(item, i) in progressItems")
.abc--step-item(:class="{ 'is__done': progressBar.index > i, 'is__current': progressBar.index === i }")
span.abc--step-dot
This is my css using SCSS
.abc--step-bar {
position: absolute;
top: 0;
left: 16.7%;
right: 16.7%;
height: 3px;
background: #e8e8e8;
}
.abc--step-bar-color {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
&:after {
color: #28A745;
content: url("../../assets/images/arrow.png");;
display: inline-block !important;
width: 0;
height: 0;
position: absolute;
right: 6px;
top: -6px;
}
}
.abc--step-dot {
display: inline-block;
width: 15px;
border-radius: 50%;
height: 15px;
background: #e8e8e8;
border: 5px solid #e8e8e8;
position: relative;
top: -7px;
.is__done &,
.is__current & {
border: 5px solid #28A745;
//background: #28A745;
}
}
I use the image for the arrow head.
I do not know how I can hide the arrow head with certain logic using Vuejs. i.e. when the progressBar.index equals 1. My arrow head is at after Pseudo-element.
I tried to put the similar example in my codepen.
https://codepen.io/steve-ngai-chee-weng/pen/xxXmRer
Use a Vue-conditional CSS class hide-arrow that hides it. JS cannot access pseudo elements directly.
.abc--step-bar-color.hide-arrow::after { content: ""; }
Please note that :after is very old CSS 2.1 syntax. In CSS 3 pseudo elements must be prefixed with ::.
I'm currently building a CSS audio player and I am setting the width of a div to represent the current progress of the audio using a [style] like below, and it works just great:
<div class="player-progress-current" [style.width.%]="(currentTime * 100)/duration"></div>
I also want to draw a little circle at the end of the progress div above by setting the 'left' CSS property of another class. This would be in english:
(Parent Width px) - (Progress Width px)
I've tried using the calc() function but it doesn't like it and the percentage calculated wouldn't know to use the width I think....
<div class="player-progress-handle" [style.left.px]="calc(100% - (currentTime * 100)/duration"></div>
The CSS classes are:
.player-progress-current {
width: 100%;
height: 1px;
background-color: red;
}
.player-progress-handle {
position: relative;
bottom: 1px;
border: 1px solid #f50;
border-radius: 100%;
height: 8px;
width: 8px;
background-color: #f50;
box-sizing: border-box;
margin-top: -4px;
margin-left: -4px;
}
Any ideas how the best way to do this is? I'm sure I can find a hacky way but would like the find the correct way
You might use :after for your handle and get rid of the calculations:
.player-progress-current {
position: relative;
width: 50%;
height: 1px;
margin: 20px 0;
background: red;
}
.player-progress-current:after {
content: '';
position: absolute;
right:-3px; bottom: 1px;
border: 1px solid #f50;
border-radius: 55%;
height: 8px;
width: 8px;
background-color: #f50;
box-sizing: border-box;
}
<div class="player-progress-current" [style.width.%]="(currentTime * 100)/duration"></div>
I have the following SASS code:
section.post {
a {
transition: all $aside-animation-time;
&::after {
position: absolute;
bottom: -.5px;
left: 0;
width: 100%;
height: 0;
content: '';
border-bottom: 1px solid $primary-color;
}
&:hover {
border-color: $hover-color;
}
}
}
What I'm doing here is adding a blue bottom border for all links. However, I noticed that when I use anchor tags with images inside, the image also has the border (since it's a link as well). Now, my goal is to append the anchor styles to text links only.
What I tried so far is using :not(img), chaining it with ::after, overriding the previous rules etc., but nothing worked as expected. Any help would be appreciated.
Currently CSS doesn't have an option to style the parent based on any child elements. If you were styling the image itself with the link it would be fine.
You might be able to use something like jQuery to add a class to any links which contain child images:
$('a:has(img)').addClass('has_img');
You can then use this with your CSS :not as in
section.post {
a:not(.has_img) {
transition: all $aside-animation-time;
&::after {
position: absolute;
bottom: -.5px;
left: 0;
width: 100%;
height: 0;
content: '';
border-bottom: 1px solid $primary-color;
}
&:hover {
border-color: $hover-color;
}
}
}
Maybe this will help you.
a {
display: block;
height: 2.5em;
position: relative;
&:after {
border-bottom: thin solid blue;
bottom: 0;
content: '';
left: 0;
position: absolute;
width: 100%;
}
&:hover:after {
border-bottom-color: red;
}
img {
display: block;
height: inherit;
position: relative;
z-index: 1;
}
}
Quick Codepen sample:
http://codepen.io/vkjgr/pen/WvMGRK
Can I achieve a custom CSS border with a button at one end which looks like this
Without url(some image link)?
Note: I want so because when I want to change color, I have to manipulate image.
I have achieved using image JS Fiddle
#stretch {
border-image: url(http://akitech.org/img/border.png) 30 30 stretch;
}
The easiest way is to use CSS pseudo-elements to create the decoration (the circle at the left) and to mask the chamfer at the right of the border (the angle at which the border-right would otherwise meet):
div {
border: 10px solid transparent;
width: 250px;
padding: 10px 20px;
position: relative;
/* this property has to be set to change the border-color: */
border-bottom-color: #f90;
}
/* common shared styles: */
div::before,
div::after {
/* to ensure the pseudo-elements are rendered: */
content: '';
/* for positioning: */
position: absolute;
/* positioning the element with its uppermost edge
against the bottom of the element, against the
upper side of the bottom-border: */
top: 100%;
/* again, set to change the color of the ends: */
background-color: #f90;
}
div::before {
/* position against the left edge: */
left: 0;
/* move the pseudo element 10px up, and
10px left: */
margin: -10px 0 0 -10px;
height: 30px;
width: 30px;
/* making the pseudo-element a circle: */
border-radius: 50%;
}
/* masking the chamfer of the border-bottom's
right-most edge: */
div::after {
left: 100%;
/* making the height/width the same width
as the border itself: */
height: 10px;
width: 10px;
}
div {
border: 10px solid transparent;
width: 250px;
padding: 10px 20px;
position: relative;
border-bottom-color: #f90;
}
div::before,
div::after {
content: '';
position: absolute;
top: 100%;
background-color: #f90;
}
div::before {
left: 0;
margin: -10px 0 0 -10px;
height: 30px;
width: 30px;
border-radius: 50%;
}
div::after {
left: 100%;
height: 10px;
width: 10px;
}
<div id="stretch">Here, the image is stretched to fill the area.</div>
In order to have these borders adapt to the length of the text, either the elements you want to have custom-bordered must themselves be able to contract to the width of the text, either using float:
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
/* forces the element to take up only that space required by
its (non-floated) contents: */
float: left;
/* forces the floated elements to the next line: */
clear: left;
}
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
float: left;
clear: left;
}
div::before,
div::after {
content: '';
position: absolute;
top: 100%;
background-color: #f90;
}
div::before {
left: 0;
margin: -10px 0 0 -10px;
height: 30px;
width: 30px;
border-radius: 50%;
}
div::after {
left: 100%;
height: 10px;
width: 10px;
}
<div>text</div>
<div>longer text</div>
<div>much longer text</div>
<div>much much much longer text</div>
Or, possibly more simply, use display: inline-block:
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
display: inline-block;
}
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
display: inline-block;
}
div::before,
div::after {
content: '';
position: absolute;
top: 100%;
background-color: #f90;
}
div::before {
left: 0;
margin: -10px 0 0 -10px;
height: 30px;
width: 30px;
border-radius: 50%;
}
div::after {
left: 100%;
height: 10px;
width: 10px;
}
<div>text</div>
<div>longer text</div>
<div>much longer text</div>
<div>much much much longer text</div>
Or display: inline (these don't automatically force new-lines between elements, obviously):
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
display: inline;
}
div {
border: 10px solid transparent;
position: relative;
border-bottom-color: #f90;
padding-left: 20px;
display: inline;
}
div::before,
div::after {
content: '';
position: absolute;
top: 100%;
background-color: #f90;
}
div::before {
left: 0;
margin: -10px 0 0 -10px;
height: 30px;
width: 30px;
border-radius: 50%;
}
div::after {
left: 100%;
height: 10px;
width: 10px;
}
<div>text</div>
<div>longer text</div>
<div>much longer text</div>
<div>much much much longer text</div>
summary:
for simplist way to this question, should not using svg, pure css can draw the shape author expected very well cause it's a combination of cycle(border radius)+rect(thicker line), let's refer to the David's answer should be the easiest and most clean way to draw that shape under text.
//below is my debugging history and tries (i searched out many ways to approach it);
//though not good answers
I use background css attribute (not OP wanted) Op used border-image also valid.
<div class="custom-border" >SOME TEXT HERE</div>
<style>
.custom-border{
padding-left:20px;
width:200px;
background:url(http://img1.wikia.nocookie.net/__cb20140224040010/shantae/images/b/bc/HGH_border_bottom.png) 0px 5px no-repeat;
background-size:contain;
height:150px;
}
</style>
later I realized OP might dislike using image traditional way, I re understand the
question is asking how to draw that shape in pure css and place it under the text and the responsive should be as flexible as the traditional way the svg shape will auto strech with the text placed on it.
after that, I've find some way to generate svg and place under text
see if it works for no image solution or you can get it improved based on fiddle
http://jsfiddle.net/hahatey/hsfxS/1464/
during the process, i've found this useful tool of generating svg from below reference url: http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html
But the flaw is it's still a fixed width solution, the line svg won't auto stretch.
Have found a unclean way to improve auto stretch though not in pure css responsive way.
but auto strech can be done by dynamically change below line
<rect stroke="#ff0000" id="svg_2" height="8" width="100%" y="27" x="40" stroke-width="5" fill="#FF0000"/>
where width="100%" or fixed value => width="function return value"; //
// during this try, i found a little bug, jquery seems unable to select svg or element inside svg? however svg element tag attribute can be written in backend languge so still valid.
//3.44
Another way without touching the inner "rect' element below "svg" tag, is to add a container to the whole thing, and using function to dynamically
assign width for the container;
like my attempt in this
fiddle: http://jsfiddle.net/hahatey/hsfxS/1468/
so at least the width can be dynamically calculated out by a function to calculate the text length of the upper text so the line will be able to strech if the calculation is accurate enough. There could be other ways to do svg auto strech with the text using pure css if other ppl find it.
Thanks.
5.02// since the author didn't say how complex the content is inside the container,
I've created a demo in pure css triggered effct --- auto strech the shape along with the text above it in below fiddle. but i said it sure has many limitations though looks similar.
http://jsfiddle.net/hahatey/a9z1kyx7/
my upper fiddle is only able to align correctly for singleline auto strech
I'm wondering if complex content (more than one line, there maybe a lot of block,inline mixed tag element inside which increases complexity for alignment) can also use css to do such decoration width auto adjustment without touching javascript or backend language.
In this jsfiddle, I'm trying to create a bookmark shape. There is only one triangle which needs to change its positioning.
<div id = "bookmark">
<div id = "rectangle"></div>
<div id = "triangle-topleft"></div>
<div id = "triangle-topright"></div>
</div>
I could easily use relative positioning and shift it, but I don't want to do it this way. I want a more malleable solution.
Instead of the shapes flowing from top to bottom. I want the last shape to flow left to right. So there are 3 shapes, the first two are in the perfect place, but the third one needs to be placed to the right of the second shape, instead of underneath it.
What CSS can I use to do this?
Add float:left; to #triangle-topleft and margin-left:100px; to #triangle-topright
#triangle-topleft {
position: static;
width: 0;
height: 0;
border-top: 100px solid black;
border-right: 100px solid transparent;
float:left;
}
#triangle-topright {
position: relative;
width: 0;
height: 0;
border-top: 100px solid black;
border-left: 100px solid transparent;
margin-left:100px;
}
jsFiddle example
First of all you do not have to declare position: static; as it is already static by default (Unless you are using responsive design where you need to reset the property value at certain point of resolution), secondly, assign position: relative; to your #bookmark and make the second triangle position: absolute;
Demo
#bookmark{
width: 200px;
position: relative;
}
#rectangle {
width: 200px;
height: 300px;
background: black;
}
#triangle-topleft {
width: 0;
height: 0;
border-top: 100px solid black;
border-right: 100px solid transparent;
}
#triangle-topright {
position: absolute;
right: 0;
width: 0;
height: 0;
border-top: 100px solid black;
border-left: 100px solid transparent;
bottom: 0;
}
Note: Make sure you do not make your first triangle position: absolute; else you need to reposition the triangles. But this is the best method you can get, as you've wrapped absolute inside a relative container.
You can also take a look at this awesome thing - Font Awesome - Bookmark, you can resize this to whatever size you want to.
The thing you are trying can be also achieved by using :before and :after pseudo along with content property. So you can get rid of the extra triangle elements.
As I said, you can create this thing with a single element.
#bookmark{
width: 200px;
position: relative;
height: 300px;
background: black;
}
#bookmark:before {
width: 0;
height: 0;
border-top: 100px solid black;
border-right: 100px solid transparent;
display: block;
content: "";
position: absolute;
bottom: -100px;
}
#bookmark:after {
position: absolute;
right: 0;
width: 0;
height: 0;
border-top: 100px solid black;
border-left: 100px solid transparent;
bottom: -100px;
display: block;
content: "";
}
Here, am using :before and :after pseudo, with display: block; and content: ""; which are essential to get this thing work, also am positioning both the elements using absolute with a value set to -100
Demo (Using single element)
Note: :before and :after pseudo can fail in older versions of IE,
but you can always use polyfills to use CSS 3 properties, also, for
more information on browser support, you can check this out.
You can just add float: left to #triangle-topleft and margin-left: 100px to #triangle-topright.
To remove unnecessary markup, you could also use :before and :after pseudo-elements instead of #triangle-*.
Add display:inline-block to both triangle shapes. They're stacking because they are defaulting to display:block.
It suffices to just add float:left to #triangle-topleft and #triangle-topright.
See the fiddle: http://jsfiddle.net/nfxYE/