I'm trying to build the following component with CSS, but I can't get the first and last point to sit flush against the ends of the line.
It must be able to support an arbitrary number of points (between 1 and 4) and I can't rely on flexbox being there either.
I have a React component that's generating HTML that looks like this:
<div class="row">
<div class="col first" style="width:33%">
<div class="marker complete"></div>
<label>Feedback</label>
</div>
<div class="col" style="width:33%">
<div class="marker partial"></div>
<label>Observation</label>
</div>
<div class="col last" style="width:33%">
<div class="marker review"></div>
<label>Documentation</label>
</div>
</div>
The JavaScript calculates the column sizes before rendering and in my codepen implementation, I'm just centering all the content in each column.
I can sort of hack a solution by using the first and last classes to relatively position the end items, but invariably when the screen size changes, I start to get the edges of the line poking out from behind the points.
Does anyone know of a more sensible layout to start building this with?
My idea would be to set row as display: table-row, and then use a pseudo element to generate the horizontal bar. However, you run into the issue that you cannot know with CSS and HTML alone what the position of the first and last circle is relative to the size of the container. Therefore, it is not possible to use a full width item.
Another approach is using the labels as root items for the pseudo elements. They are always the full width of the column, so they give a nice indication what needs to be used.
The following proposed solution should work with IE9. The only special thing that is used is calc and after. (Instead of calc you can also use a transform: translate if you want.)
The basic idea is to use a table row, which would automatically scale nicely, and then use the labels as roots on which you can build the progress bar.
label:after {
content: "";
height: .5em;
background: #e2e2e2;
width: 100%;
position: absolute;
top: calc((100% - 1.5em) / 2); /* -1 to compensate text, -.5 for height bar */
left: 0;
z-index: -1;
}
.first label:after, .last label:after {
width: 50%;
}
.first label:after {
left: auto;
right: 0;
}
.single label:after {content: none;}
Here ya go. I assume this is what you are looking for.
<div class="row">
<div class="col" style="width:33%">
<div class="marker marker1 complete"></div>
<label>Feedback</label>
</div>
<div class="col2" style="width:33%">
<div class="marker marker2 partial"></div>
<label>Observation</label>
</div>
<div class="col3" style="width:33%">
<div class="marker marker3 review"></div>
<label>Documentation</label>
</div>
</div>
https://jsfiddle.net/norcaljohnny/e6nm2rbv/
*if JS was/is allowed I can put some conditions in it based on number and word length and adjust marker indentions.
Basically I used display blocks, margins and secondary marker classes for each block.
.row {
display: table;
margin: 0 auto;
position: relative;
width: 100%;
}
.col {
display: table-cell;
width: 33%;
text-align: center;
}
.marker {
width: 30px;
height: 30px;
background-color: lightgray;
border-radius: 30px;
margin: 0 auto;
}
.complete {
background-color: blue;
}
.partial {
background-color: blue;
box-sizing: border-box;
border: 8px solid lightgray;
}
.review {
background-color: lightblue;
}
.col:not(:last-child) > .marker:after {
content: '';
display: inline-block;
width: 67%;
height: 0;
border: 3px solid lightgray;
position: absolute;
left: 16.5%;
top: 12.5px;
z-index: -10;
}
/* ------------------------------------------- */
.wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 0 100px;
}
.point {
height: 30px;
background-color: lightgray;
border-radius: 30px;
flex: 0 0 30px;
position: relative;
}
.line {
height: 0;
border: 3px solid lightgray;
flex: 1 0;
}
.blue {
background-color: blue;
}
.lightblue {
background-color: lightblue;
}
.border {
background-color: lightgray;
background-image: radial-gradient(at center center, blue 0, blue 8px, transparent 8px, transparent 100%);
}
.point label {
position: absolute;
left: -50%;
top: 100%;
text-align: center;
}
<h1>Non flex</h1>
<div class="row">
<div class="col first">
<div class="marker complete"></div>
<label>Feedback</label>
</div>
<div class="col">
<div class="marker partial"></div>
<label>Observation</label>
</div>
<div class="col last">
<div class="marker review"></div>
<label>Documentation</label>
</div>
</div>
<h1>Flex</h1>
<div class="wrapper">
<div class="point blue">
<label>Feedback</label>
</div>
<div class="line"></div>
<div class="point blue border">
<label>Observation</label>
</div>
<div class="line"></div>
<div class="point lightblue">
<label>Documentation</label>
</div>
</div>
Related
It's a little bit hard to explain, that's why i also can't find the answer on Google.
I'm working with Bootstrap 3, and i need a full width background image. On top of that 2 transparent color backgrounds. I made a example image to make it all clear:
1+2: combined transparent color background
3+4: combined transparent color background
1+2+3+4: combined background image (lowest layer)
Does anyone know if this is possible and how? Thanks for your help!
Yes, using the techniques outlined in this question but extending it to the columns.
The Codepen Demo (below) shows the result better than the Stack Snippet which is included for reference.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
/* prevent scrollbar */
}
.container {
width:50%;
margin:auto;
margin-top: 1em;
position: relative;
overflow: visible;
}
.extra:before {
content: '';
display: block;
/* override bootstrap */
position: absolute;
top: 0;
left: 50%;
width: 100vw;
height: 100%;
transform: translate(-50%, 0);
}
[class*="col"] {
border: 2px solid grey;
min-height: 120px;
position: relative;
}
.left:before {
content: '';
position: absolute;
height: 100%;
width: 100vw;
top: 0;
right: 0;
background: rgba(255, 0, 0, 0.5)
}
.right:before {
content: '';
position: absolute;
height: 100%;
width: 100vw;
top: 0;
left: 0;
background: rgba(0, 0, 255, 0.25);
}
<div class="container extra">
<div class="row">
<div class="col-sm-4 left"></div>
<div class="col-sm-8 right"></div>
</div>
</div>
Codepen Demo
I think i figured it out.. Thanks to Paulie_D
Very simple example:
HTML:
<div class="fullwidth">
<div class="cell red20">xxx</div>
<div class="container cell">
<div class="row">
<div class="col-sm-4 red20">xx</div>
<div class="col-sm-8 red50">xx</div>
</div>
</div>
<div class="cell red50">xxx</div>
</div>
CSS:
.fullwidth {
background: url('http://www.ustudy.eu/nl/wp-content/uploads/2013/10/Test-taking-from-Flickr.jpg');
display:table;
width:100%;
}
.cell{
display:table-cell;
vertical-align:top;
}
.red20{
background-color:rgba(255,0,0,0.2);
}
.red50{
background-color:rgba(255,0,0,0.5);
}
Link to jsfiddle: https://jsfiddle.net/DTcHh/14045/
Okay, so I thought that the grid was perfectly aligned to the center, only to realise that it was a few pixels out. I completely stripped all of my attempts at centering and looked online but couldn't find anything.
I know I can use CSS Grids, Flexbox etc. but I am trying to learn how to create websites without using any aid. So I can learn the reasoning behind things.
Fiddle:
https://jsfiddle.net/8L9ye7nj/5/
Grid HTML:
<div class="box-wrapper">
<div class="box-container">
<div class="box" id="stethoscope">
<div class="box-label">
<p>Book an appointment</p>
</div>
</div>
<div class="box" id="prescription">
<div class="box-label">
<p>Request a repeat prescription</p>
</div>
</div>
<div class="box" id="group">
<div class="box-label">
<p>Join the Patient Group</p>
</div>
</div>
</div>
</div>
Grid CSS:
.box {
float: left;
width: 25%;
height: 300px;
background-color: #252625;
color: #FFF;
position: relative;
padding: 15px;
margin: 0.5%;
}
.box-label {
position: absolute;
bottom: 0;
text-align: center;
background-color: rgba(0,0,0,0.5);
width: 100%;
padding: 7px 0;
left: 0;
}
.box-label:hover {
animation: box-stretch 1s forwards ease-in-out;
cursor: pointer;
}
.box-container {
width: 90%;
}
.box-container::after {
content: "";
clear: both;
display: table;
}
.box-wrapper {
background-color: #B21645;
padding: 30px;
}
How can you divide the box and center them?
You can use calc to use mathematical expressions to calculate height, widths etc in css. You can divide the width by three here for the box.
.box {
display: inline-block;
width: calc(100% / 3);
}
Things to consider
Mind the space between inline-block elements. You can read more about
that here.
Avoid using floats as much as possible. Most layouts done with float can be achieved with inline-block. Floats are simply meant to take an element, put it to one side, and let other content flow around it. That’s all.
box-wrapper and box-container either one is only needed to wrap the contents inside.
Code Snippet
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
.box-wrapper {
background-color: #b21645;
padding: 20px;
}
.box {
position: relative;
display: inline-block;
width: calc(100% / 3);
padding: 0 10px;
height: 300px;
overflow: hidden;
}
.box img {
height: 100%;
width: 100%;
object-fit: cover;
object-position: left top;
}
.box-label {
position: absolute;
bottom: 0;
width: calc(100% - 20px);
text-align: center;
background-color: rgba(0, 0, 0, .6);
padding: 10px 0;
transition: padding 0.3s;
}
.box-label:hover {
padding: 25px 0;
}
.box-label p {
font-family: Helvetica;
color: white;
font-size: 20px;
}
<div class="box-wrapper">
<div class="box">
<img src="https://images.unsplash.com/photo-1509027572446-af8401acfdc3?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ef8f839186c5a6055d2802005b575194&auto=format&fit=crop&w=500&q=60" alt="" />
<div class="box-label">
<p>Some Title Here</p>
</div>
</div><div class="box">
<img src="https://images.unsplash.com/photo-1509027572446-af8401acfdc3?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ef8f839186c5a6055d2802005b575194&auto=format&fit=crop&w=500&q=60" alt="">
<div class="box-label">
<p>Some Title Here</p>
</div>
</div><div class="box">
<img src="https://images.unsplash.com/photo-1509027572446-af8401acfdc3?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ef8f839186c5a6055d2802005b575194&auto=format&fit=crop&w=500&q=60" alt="">
<div class="box-label">
<p>Some Title Here</p>
</div>
</div>
</div>
I've come up with what seems like a very hacky, non-semantic way to code a design that I'd like to use. Basically, it's a set of 4 equal-sized circles, distributed so their centers are the same as those of equilateral triangles. I've used a bunch of presentational divs to solve two issues: (1) to get the spacing of the circles right, I need their bounding boxes to overlap; and (2) to vertically space text in the circles without changing their size, it seems like I need to use display:table in my CSS.
It works, but I hate it, and I feel like there has to be a better way. I am new to CSS, and this method is the result of a fair amount of research about how to solve this design problem.
The design is at this codepen: http://codepen.io/bhagerty/pen/rejEPZ
(I put borders on a bunch of the elements just to show the structure.)
Here is the HTML:
<body>
<h1 id="home_title">test</h1>
<div id="container_1">
<div id="picture" class="box">
<div class="circle_outer">
<div class="circle_inner">
<div class="inner-text">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/%22In_Which_We_Serve%22_Advertisement_1943.jpg/1024px-%22In_Which_We_Serve%22_Advertisement_1943.jpg" width=100%; />
</div>
</div>
</div>
</div>
<div id="dog" class="box">
<div class="circle_outer">
<div class="circle_inner">
<div class="inner-text">
dog
</div>
</div>
</div>
</div>
<div id="shoes" class="box">
<div class="circle_outer">
<div class="circle_inner">
<div class="inner-text">
shoes
</div>
</div>
</div>
</div>
<div id="dance" class="box">
<div class="circle_outer">
<div class="circle_inner">
<div class="inner-text">
dance
</div>
</div>
</div>
</div>
<div id="footer_1">
Footer<br>
test
</div>
</div>
</body>
Here is the CSS:
* {
box-sizing: border-box;
padding: 0;
margin: 0;
font-size: 16px;
}
h1#home_title {
text-align: center;
font-size: 3rem;
margin: 0;
padding: .1rem 0 .5rem 0;;
background-color: grey;
}
div#container_1 {
border: green solid 5px;
width: 320px;
margin: auto;
position: relative;
}
div.box {
border: red solid 1px;
position: absolute;
width: 53.6%;
text-align: center;
background-color: transparent;
}
/*pseudo-element to give relative height,
per http://jsfiddle.net/simevidas/PFPDU/
and http://www.mademyday.de/css-height-equals-width-with-pure-css.html */
div.box::before {
content: "";
display: block;
padding-top: 100%;
height: 0;
}
/* if inner text has position relative, it influences the size of the containing box */
/*setting all of the positions to zero forces it inside the circle for some reason */
.circle_outer {
position: absolute;
overflow: hidden;
border: black solid 2px;
border-radius: 50%;
/* to create breathing room all around, set top and left to 1/2 of 100% - width (where width = height) */
top: 5%;
left: 5%;
width: 90%;
height: 90%;
}
.circle_inner {
/* border: grey solid 5px; */
display: table;
width: 100%;
height: 100%;
}
.inner-text {
display: table-cell;
/* border: green solid 2px; */
font-size: 2em;
vertical-align: middle;
}
/*First bounding box is at upper left corner */
div#picture {
overflow: hidden;
left: 0;
margin-top: 0;
}
/*Percent positions all based on W, derived from fact
that bounding boxes circumscribe tangent circles, and
circle centers are connected by equilateral triangles */
div#dog {
left: 46.4%;
margin-top: 26.8%;
}
div#shoes {
left: 0;
margin-top: 53.6%;
}
div#dance {
left: 46.4%;
margin-top: 80.4%;
}
div#footer_1 {
border: red solid 2px;
position: relative;
width: 100%;
left: 0;
margin-top: 137%;
text-align: center;
background-color: blue;
}
I much appreciate any thoughts or help. Thanks!
Well, IMO what you've done is really good. I wouldn't be too concerned about the extra divs.
But, it can be done with fewer divs, making use of float and margins.
Codepen is here
html {
font-size: 16px;
}
h1#home_title {
text-align: center;
font-size: 3rem;
margin: 0;
padding: .1rem 0 .5rem 0;;
background-color: grey;
}
div#container_1 {
border: green solid 5px;
width: 320px;
margin: auto;
position: relative;
box-sizing: border-box;
}
div.box {
border: red solid 1px;
position: relative;
float:left;
width: 53.6%;
text-align: center;
background-color: transparent;
box-sizing:border-box;
margin-bottom:-27%;
}
div.box:nth-child(2n) {
float:right;
}
div.box:nth-child(2n+1) {
float:left;
}
/*pseudo-element to give relative height,
per http://jsfiddle.net/simevidas/PFPDU/
and http://www.mademyday.de/css-height-equals-width-with-pure-css.html */
div.box::before {
content: "";
display: block;
padding-top: 100%;
height: 0;
}
/* if inner text has position relative, it influences the size of the containing box */
/*setting all of the positions to zero forces it inside the circle for some reason */
.featuring {
position: absolute;
overflow: hidden;
border: black solid 2px;
border-radius: 50%;
/* to create breathing room all around, set top and left to 1/2 of 100% - width (where width = height) */
top: 5%;
left: 5%;
width: 90%;
height: 90%;
font-size: 2em;
}
.featuring:before {
content:'';
margin-left:-0.25em;
display:inline-block;
vertical-align:middle;
height:100%;
}
/*Percent positions all based on W, derived from fact
that bounding boxes circumscribe tangent circles, and
circle centers are connected by equilateral triangles */
div#footer_1 {
border: red solid 2px;
position: relative;
width: 100%;
left: 0;
margin-top: 137%;
text-align: center;
background-color: blue;
clear:both;
}
<body>
<h1 id="home_title">test</h1>
<div id="container_1">
<div id="picture" class="box">
<div class="featuring">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/%22In_Which_We_Serve%22_Advertisement_1943.jpg/1024px-%22In_Which_We_Serve%22_Advertisement_1943.jpg" width=100%; />
</div>
</div>
<div id="dog" class="box">
<div class="featuring">
dog
</div>
</div>
<div id="shoes" class="box">
<div class="featuring">
shoes
</div>
</div>
<div id="dance" class="box">
<div class="featuring">
dance
</div>
</div>
<div id="footer_1">
Footer<br>
test
</div>
</div>
</body>
Here is a simple site: 1 featured post and 3 small boxes under. I have a darkening effect on hover. The problem is when I add the small boxes. It stops working =(
<div class="bigBox">
<div class="featured_post">
<span></span>
<div class="category">Stuff</div>
<h1>Text will go here</h1>
</div>
</div>
<div class="small_boxes">
<div class="box01">
<span></span>
<div class="category">Stuff</div>
<h1>Text will go here</h1>
</div>
FULL CODE WITH CSS:
1 small box (work) http://codepen.io/tsalexey544/pen/wBExPJ?editors=110
3 small boxes (doesnt work) http://codepen.io/tsalexey544/pen/xbaJpe?editors=110
your .small_boxes (box01, box02, box03) miss a position: relative. If you add that, you are done.
Your boxes float in their parent. Their parent has position: relative. The spans get the full height+width of that parent, which is 0x0, since its children float.
.small_boxes <-- position: relative. 0x0
.box01/02/03 <-- float: left
span <-- 100% of .small_boxes = 0x0
What you want:
.small_boxes
.box01/02/03 <-- float: left, position: relative;
span <-- 100% of .box = desired effect
you could use pseudo elements to achieve this effect, which would reduce markup considerably:
.cont {
position: relative;
background: url(http://japanpapa.ru/fun/jpap/img/post01.jpg);
background-size: 100% 100%;
height: 100px;
width: 100px;
displaY: inline-block;
margin: 10px;
}
.text {
display: inline-block;
color: white;
font-size: 20px;
text-align: center;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
line-height:100px;
}
.cont:before {
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
background: black;
transition: all 0.4s;
opacity: 0;
}
.cont:hover:before {
opacity: 0.6;
}
<div class="cont">
<div class="text">text1</div>
</div>
<div class="cont">
<div class="text">text2</div>
</div>
<div class="cont">
<div class="text">text3</div>
</div>
I have a selection of squares (squares turned 45° to look like diamonds) which I want to use to make up a big diamond shape with a central red diamond.
I am having issues organising the diamonds themselves and the href seems to fail.
How do I position the responsive diamonds in a regular grid?
Her is my code:
body {
background: black;
color: #000000;
font: 13px georgia, serif;
line-height: 1.4;
font-weight: lighter;
text-rendering: optimizelegibility;
}
#diamond {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom-color: white;
position: relative;
top: -50px;
}
#diamond:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: white;
}
#diamond_red {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom-color: #AA1C08;
position: relative;
top: -50px;
}
#diamond_red:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: #AA1C08;
}
<a class="navigation">
<center>
<div id="diamond"></div>
<div id="diamond"></div>
<div id="diamond" href="/photos/"></div>
<div id="diamond_red"></div>
<div id="diamond" href="/projects/"></div>
<div id="diamond"></div>
<div id="diamond"></div>
<div id="diamond" href="/archive/"></div>
</center>
</a>
The responsive grid of diamons:
I don't think you have the right aproach to achieve a regular responsive diamond grid layout. It would be much simpler to:
create a responsive grid of squares (3x3 or whatever grid you feel like)
then rotate the grid 45 degrees.
That way you won't have to fiddle with borders, pseudo elements (:after, :before) and positioning each diamond.
Here is a responsive example
It uses percentage width and padding-bottom to keep the diamonds responsive and transform:rotate(45deg); to rotate te whole grid and make it look like a diamond grid:
body{background:#000;}
#big_diamond {
width: 50%;
margin:15% auto;
overflow:hidden;
transform: rotate(45deg);
}
.diamond {
position: relative;
float: left;
width: 31.33%;
padding-bottom: 31.33%;
margin: 1%;
background: #fff;
transition:background-color .4s;
}
.diamond a {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
}
#red{background-color: #AA1C08;}
.diamond:hover, #red:hover{background-color:darkorange;}
<div id="big_diamond">
<div class="diamond"></div>
<div class="diamond"></div>
<div class="diamond"></div>
<div class="diamond"></div>
<div class="diamond" id="red"></div>
<div class="diamond"></div>
<div class="diamond"></div>
<div class="diamond"></div>
<div class="diamond"></div>
</div>
As other people have mentioned, there are some errors in your HTML that I corrected like: Ids need to be unique and href can't be used on divs.
You're going to need to be more specific / clear on your first question.
First of all, you are using the ID 'diamond' many times. IDs are meant to be unique and used for one element. You should be using classes for this, not IDs.
Second, you can't use href within div tags. You could wrap the divs in a tags like this:
<div class="diamond"></div>
Or, even better so that the whole shape is clickable you can put the a inside of the div and make the a a block level element that is 100% width and height like this:
<div class="diamond"></div>
div a{
width: 100%;
height: 100%;
display: block;
}
JSFiddle Example: http://jsfiddle.net/kQj24/1/
This html has fallback for browsers that don't support transform in that the diamond becomes a square. Also the <div> elements can be wrapped in <a> tags using this method without altering any existing css rules for a. If transform isn't supported the text inside the square class doesn't rotate either.
<center>
<div class="diamond">
<div class="row">
<div class="square"><p>Text</p></div>
<div class="square"></div>
<div class="square"><p>Text</p></div>
</div>
<div class="row">
<div class="square"><p>Text</p></div>
<div class="square red"><p>Text</p></div>
<div class="square"><p>Text</p></div>
</div>
<div class="row">
<div class="square"><p>More</p></div>
<div class="square"></div>
<div class="square"><p>Text</p></div>
</div>
</div>
</center>
CSS, using your existing body rule:
.diamond {
padding-top: 50px;
transform:rotate(45deg);
-ms-transform:rotate(45deg);
-webkit-transform:rotate(45deg);
}
.square {
background-color: white;
display: inline-block;
height: 50px;
overflow: hidden;
width: 50px;
}
.square:hover {
background-color: green;
}
.square p {
transform:rotate(-45deg);
-ms-transform:rotate(-45deg);
-webkit-transform:rotate(-45deg);
}
.red {
background-color: red;
}
http://jsfiddle.net/5Q8qE/8/