Tips for keeping a focus ring secure on a see-through object

I'm currently working on incorporating a profile picture input in a form that allows users to select a new image when clicked. The standard method seems to involve using an input with the type of "file" and then hiding it using different techniques. I personally find setting opacity:0 as the most viable option, as it keeps the element in the DOM while still detecting clicks or focus.

However, having an input with zero opacity also means that there won't be a visible focus ring even when the element is technically in focus. What are my options to ensure that a focus ring appears when the input is focused? Thank you for your help.

.profile-pic {
  width: 156px;
  height: 156px;
  border-radius: 50%;
  position: relative;
  /* overflow: hidden; */
}

.profile-pic input[type='file'] {
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  z-index: 10;
}

.profile-pic__img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
}

.profile-pic__img img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.65);
  transition: filter 0.2s ease-in-out;
  cursor: pointer;
}

.profile-pic__img img:hover {
  filter: brightness(0.5);
}

.profile-pic__text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 90%;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 5;
}

.profile-pic__text .fa-camera {
  color: #fff;
}

.profile-pic span {
  color: #fff;
  text-align: center;
  font-size: 16px;
  font-style: normal;
  font-weight: 400;
  line-height: normal;
  width: 90%;
}
<div class="profile-pic">
  <input type="file" />
  <div class="profile-pic__img">
    <img src="[TEST_URL]" alt="" />
  </div>
  <div class="profile-pic__text">
    <i class="fas fa-camera"></i>
    <span>Click to change photo</span>
  </div>
</div>

Answer №1

Utilize the :focus-within pseudo-class on the element with the class .profile-pic to apply a distinct style when the transparent input field is in focus.

.profile-pic {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  position: relative;
}

.profile-pic:focus-within {
    box-shadow: 0 0 10px rgba(0,0,0,0.5);
}

.profile-pic input[type='file'] {
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.profile-pic__img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.profile-pic__text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.profile-pic span {
  color: #333;
  font-size: 14px;
}
<div class="profile-pic">
  <input type="file" />
  <div class="profile-pic__img">
    <img src="[IMAGE_URL]" alt="" />
  </div>
  <div class="profile-pic__text">
    <span>Click to upload photo</span>
  </div>
</div>

Answer №2

Is it necessary to have an invisible element in order for a focus ring to appear?

You might want to consider adding a focus ring to the visible and interactive .profile-pic element instead.

To make the .profile-pic element focusable, simply add a tabindex="0" attribute to it. Then, style a focus ring by selecting it with CSS using .profile-pic:focus.

While I may not have directly answered your question, I hope this guidance proves to be useful.

Answer №3

Essentially the same solution as Quentin's, but I opted to maintain the pseudo-class on the input by utilizing a box-shadow instead of an outline. It's essentially six of one, half a dozen of the other.

.profile-pic {
  width: 156px;
  height: 156px;
  border-radius: 50%;
  position: relative;
  /* overflow: hidden; */
}

.profile-pic input[type='file'] {
  opacity: 0.2;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  z-index: 10;
}

.profile-pic input[type='file']:focus-within {
  box-shadow: 0 0 1px 5px blue;
}

.profile-pic__img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
}

.profile-pic__img img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.65);
  transition: filter 0.2s ease-in-out;
  cursor: pointer;
}

.profile-pic__img img:hover {
  filter: brightness(0.5);
}

.profile-pic__text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 90%;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 5;
}

.profile-pic__text .fa-camera {
  color: #fff;
}

.profile-pic span {
  color: #fff;
  text-align: center;
  font-size: 16px;
  font-style: normal;
  font-weight: 400;
  line-height: normal;
  width: 90%;
}
<div class="profile-pic">
  <input type="file" />
  <div class="profile-pic__img">
    <img src="[TEST_URL]" alt="" />
  </div>
  <div class="profile-pic__text">
    <i class="fas fa-camera"></i>
    <span>Click to change photo</span>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error in WebGL rendering: attribs are not configured properly

Below is the code for my vertex shader: attribute vec3 aVertexPosition; attribute vec4 aVertexColor; attribute float type; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { gl_Positi ...

Exclusive Design for Progress Bar in HTML and CSS

I am currently working on creating a unique progress bar with numbers at both ends, where the left number represents the current value and the right number represents the maximum or target value. Although I have managed to display the two numbers, I am fac ...

Determining the ideal placement for business logic within a Node.js and Express.js RESTApi

My current Node+Express.js RESTApi structure consists of the following components: - controllers - db -- models -- config -- migrations - helpers - routes - services - test package.json index.js I am wondering where would be the most appropriate place to ...

Exploring the capabilities of using Next.js with grpc-node

I am currently utilizing gRPC in my project, but I am encountering an issue when trying to initialize the service within a Next.js application. Objective: I aim to create the client service once in the application and utilize it in getServerSideProps (wit ...

Unable to display PHP response in a div using AJAX - issue persisting

Hey there! I'm currently working on a project where I want the form submission to load a response into a div without refreshing the page. I've looked at various examples of ajax forms with PHP online, but haven't been able to solve my issue ...

The correct conclusion is reached by the function when the console.log statement is placed above the function call

By moving the console.log above the function call, the correct conclusion is reached. I double-checked multiple times by toggling the console.log on and off. Running on node.js v16.4.2. The input data is accurate. I attempted to replicate the issue in a di ...

What happens in the React tutorial when the clear fix is commented out and the appearance does not change?

Currently, I am working through the React tutorial and have encountered a question regarding their starter code: class Square extends React.Component { render() { return ( <button className="square"> {/* TODO */} </butto ...

Having trouble retrieving req.session variables in Express/NodeJS?

I have come across various versions of this particular question, however, none of them seem to address my issue directly. My current objective is to establish a Node.js server using Express. Below is my existing server configuration: var express = require ...

Leveraging the XMLHTTP object to extract data from websites with VBA

I am currently working on extracting the "key people" information from a Wikipedia page: https://en.wikipedia.org/wiki/Abbott_Laboratories and inserting that data into my Excel spreadsheet. I have successfully achieved this using xml http, which I find ef ...

Retrieving the value of the name attribute from a div using the $_POST method

Seeking to retrieve the value of $_POST["number"] from the <div name="number" class="total"></div> HTML element with the total class attached. var count = 0; $('button').click(function(){ count++; count > 3 || $('.to ...

CSS word-wrap property not functioning within a div element

I am currently using the ionic framework to iterate words from a database. However, I am facing an issue where the words span across the div and do not break when reaching the end of the div; instead, they are truncated. I have tried applying the break-wor ...

Angular Universal Resolve

I am trying to ensure that an asynchronous call completes before any of my routes are resolved by modifying route.resolve as follows: var originalWhen = $routeProvider.when; $routeProvider.when = function(path, route) { route.resolve || (route.resolve ...

What is the best way to obtain a unique result for a single cell without encountering any duplicates when using the Angular

Currently, I have functional code that successfully passes data from a dialog window to a table. Everything works fine for a single row, but when I try to add multiple rows to the table, I get results for several columns simultaneously. Is there a way to o ...

Organize the structure of a JSON object in AngularJS to generate a hierarchical unordered list

Greetings! I am working with a RESTful API that returns a JSON object structured like this: { data: [ { id: 4, name: "Naranja", cant_portion: 2, portion_name: "Piezas", foodgroup_name: "Frutas" } ...

Position SVG's in relation to one another

I have two SVG's and I'm looking to position the second SVG in the top right corner of the first SVG. In this example, I want to place the exclamation SVG in the TOP RIGHT corner of the first SVG. Can someone provide guidance on what changes I n ...

The order of event handlers in jQuery

I am currently setting up event binding for a text element dynamically. Take a look at the following code snippet: <input type="text" id="myTxt" /> <script type="text/javascript"> function attachEvent1(element){ element.keyup(func ...

Assigning multiple identifiers to a single element

Multiple posts have emphasized the importance of using an ID only once. But, I'm facing a situation where I need to pass 2 PHP variables to my JavaScript. I initially thought of using document.getElementById, but since IDs must be unique, this approa ...

Issue with Error in Expanding Label in Material-Ui using React

I have managed to increase the size of the Label in the TextField component of my React application. However, I am encountering an issue where it overlaps some text on its right when it shrinks. https://i.sstatic.net/BikHJ.png Here is the link for refere ...

Facing an issue where WordPress AJAX is not showing the expected content

Currently, I am in the process of creating a WordPress website that will feature an initial display of two rows of images. Upon clicking a button, two more rows should dynamically appear. There are four key files involved in this project: case-study-ca ...